英文:
Oracle APEX (21.2) Database Design - Split Numbers vs Normalization
问题
I know this is overall a database design question, but I think there is validity of listing it with APEX due to the nature of the implementation I am thinking of with use of APEX_STRING.SPLIT_NUMBERS api.
With that out of the way, I have a consent form table that once created will need to be assigned to different 'target' groups (e.g. School Pyramid, School Level [High School, Middle School, Elementary], Grade Level [1-12], or even specific schools [by a School ID]). More than 1 pyramid can be targeted (total of 5), more than 1 school can be targeted (up tp 10) for a given consent form.
My initial thought was a table that has all these target groups (with associated reference/lookup tables REF_PYRAMID, REF_SCHOOL_LEVEL, REF_SCHOOL). Then store the IDs in the associated column as a list of numbers (eg. 2:12:13). Then I would use APEX_STRING.SPLIT_NUMBERS & MEMBER OF when I need to run SQL check to see if parent is part of an authorized target & should have access to the consent form.
I am not used to storing info this way so wondering if there are any downsides of this approach? This keeps the record flat and allows the option to make a consent form school-wide, which is just Y/N option not multiple targets, like the others.
dpc_consent_form_target {
target_id number [primary key]
consent_form_id number [ref: > dpc_consent_form.consent_form_id]
school_wide char(1) [chk 'Y','N']
pyramid_id number
school_id number
school_level_id number
grade_id number
}
My second thought was to normalize the design, like I usually would, so that each, say School, would have it's own record in a TARGET table, but then I'm not sure how best to handle the single "record" of school-wide.
table dpc_consent_form_target {
target_id number [primary key]
consent_form_id number [ref: > dpc_consent_form.consent_form_id]
target_type_id number [ref: > dpc_ref_target_type.target_type_id]
target_value_id number
created_by varchar2(50)
created_date timestamp
updated_by varchar2(50)
updated_date timestamp
}
table dpc_ref_target_type {
target_type_id number [primary key]
target_type_name varchar2(50)
active_flag char(1)
created_by varchar2(50)
created_date timestamp
updated_by varchar2(50)
updated_date timestamp
deleted_by varchar2(50)
deleted_date timestamp
}
TARGET TYPE VALUES:
1 - pyramid_id
2 - school_level_id
3 - school_id
4 - grade_id
5 - school_wide
Thanks in advance for any advice.
英文:
I know this is overall a database design question, but I think there is validity of listing it with APEX due to the nature of the implementation I am thinking of with use of APEX_STRING.SPLIT_NUMBERS api.
With that out of the way, I have a consent form table that once created will need to be assigned to different 'target' groups (e.g. School Pyramid, School Level [High School, Middle School, Elementary], Grade Level [1-12], or even specific schools [by a School ID]). More than 1 pyramid can be targeted (total of 5), more than 1 school can be targeted (up tp 10) for a given consent form.
My initial thought was a table that has all these target groups (with associated reference/lookup tables REF_PYRAMID, REF_SCHOOL_LEVEL, REF_SCHOOL). Then store the IDs in the associated column as a list of numbers (eg. 2:12:13). Then I would use APEX_STRING.SPLIT_NUMBERS
& MEMBER OF
when I need to run SQL check to see if parent is part of an authorized target & should have access to the consent form.
I am not used to storing info this way so wondering if there are any downsides of this approach? This keeps the record flat and allows the option to make a consent form school-wide, which is just Y/N option not multiple targets, like the others.
dpc_consent_form_target {
target_id number [primary key]
consent_form_id number [ref: > dpc_consent_form.consent_form_id]
school_wide char(1) [chk 'Y','N']
pyramid_id number
school_id number
school_level_id number
grade_id number
}
My second thought was to normalize the design, like I usually would, so that each, say School, would have it's own record in a TARGET table, but then I'm not sure how best to handle the single "record" of school-wide.
table dpc_consent_form_target {
target_id number [primary key]
consent_form_id number [ref: > dpc_consent_form.consent_form_id]
target_type_id number [ref: > dpc_ref_target_type.target_type_id]
target_value_id number
created_by varchar2(50)
created_date timestamp
updated_by varchar2(50)
updated_date timestamp
}
table dpc_ref_target_type {
target_type_id number [primary key]
target_type_name varchar2(50)
active_flag char(1)
created_by varchar2(50)
created_date timestamp
updated_by varchar2(50)
updated_date timestamp
deleted_by varchar2(50)
deleted_date timestamp
}
TARGET TYPE VALUES:
1 - pyramid_id
2 - school_level_id
3 - school_id
4 - grade_id
5 - school_wide
Thanks in advance for any advice.
答案1
得分: 3
请注意,代码部分不需要翻译,以下是翻译好的内容:
然后将这些ID存储在相关列中,作为一组数字(例如2:12:13)。
不要这样做。
Apex会连接RETURN
值,例如Shuttle项目,一切都在Apex世界中正常工作。但是,一旦您离开Apex并必须编写基于这种数据的查询,您将不得不将值拆分为行,以便将它们连接到其他表格。
这是可行的,可以完成,没有问题;但是,这不是正确的方法,因为数据模型没有规范化。此外,您无法在其上创建任何有意义的索引,因为您将对冒号分隔的字符串进行索引,而不是每个值;当您具有小数据集时,性能没有差异,但在大数据集上性能将受到影响。
该怎么办?创建一个子表格,通过外键约束引用其主表格。
英文:
> Then store the IDs in the associated column as a list of numbers (eg. 2:12:13).
Don't do that.
Apex concatenates RETURN
values for e.g. Shuttle items and everything works just fine in Apex world. However, as soon as you step out of it and have to write queries based on such a data, you'll have to split values into rows so that you could join them to other table(s).
It works, can be done, no problem; however, that's not the way to do it because data model isn't normalized. Also, you can't create any meaningful index on it because you'd be indexing a colon-separated string, not each value within; no difference in performance when you have a small data set, but it will suffer on large data sets.
What to do? Create a child table which will reference its master table via foreign key constraint.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论