我经常看到这种设计模式,但没有名字。我很想知道--设计者称之为--以及他们如何使用合理的DB设计来处理它。
举个简单的例子,假设学生有等级(1-8).如果该学生的年级等级为7或8,那么他们可能是荣誉学生。那么,如何针对学生跟踪这一位标志,因为它只适用于某一年级的学生?
发布于 2012-06-13 17:28:17
我将此称为数据依赖。并不是所有的数据依赖都可以直接或方便地用关系分解来建模。通过一个check约束,可以很容易地处理这个问题:
CREATE TABLE Students (
id SERIAL PRIMARY KEY, -- for example, something else in reality
grade INTEGER NOT NULL,
honors BOOLEAN,
CONSTRAINT ensure_honors_grade
CHECK((honors IS NULL AND grade < 7) OR
(honors IS NOT NULL AND grade >= 7))
);另一种解决方案可能是使用两个表:
CREATE TABLE Students (
id SERIAL PRIMARY KEY,
grade INTEGER NOT NULL,
CONSTRAINT id_grade_unique UNIQUE (id, grade) -- needed for FK constraint below
);
CREATE TABLE Honors (
student_id INTEGER NOT NULL,
grade INTEGER NOT NULL,
honors BOOLEAN NOT NULL,
CONSTRAINT student_fk FOREIGN KEY (student_id, grade) REFERENCES Students(id, grade),
CONSTRAINT valid_grade CHECK(grade >= 7)
);这种替代设计更明确地说明了年级与是否有荣誉旗之间的关系,并为7至8年级学生的进一步分化留出了空间(尽管表名需要改进)。如果你只有一个属性,荣誉布尔,那么这可能是过头了。正如@BrankoDimitrijevic所提到的那样,这并不是仅仅因为分数是7或8就强制在Honors中存在行,而且您还支付了一个本来就不需要的索引。因此,有一些权衡;这肯定不是仅有的两种可能的设计;布兰科还建议使用触发器。
当涉及到OO设计时,@Ryan是正确的,但是对于正确的关系数据库设计,通常不会通过识别继承模式来解决问题。这就是OO的观点。关注您的访问模式以及您的代码如何获取数据总是很重要的,但是在关系数据库设计中,首先要争取数据库的规范化和灵活性,其次是代码的灵活性,因为数据中总是会有多个代码库,不管访问代码有多大错误,您都希望确保数据总是有效的。
发布于 2012-06-13 17:17:09
您需要考虑类模型以及它的使用方式。您认为Honors是Student的布尔标志吗?比如if (grade > 6) Student.honor = true
通常,您可以将其视为继承映射的一种情况。将其视为Student是父类,而您的子类是HonorStudent。在关系数据库中映射继承有多种方法。
您可以将所有内容映射到单个表中,就像基类和子类中的所有属性一样,但是其中一些属性将被设置为空或空。例如,如果HonorStudent有一个属性X,那么在将一个学生映射到表时,您会将属性X设置为NULL。
另一种情况是为每个具体类提供一个表。因此,您将有一个单独的表为学生和HonorStudent。
您还可以为学生和HonorStudent创建一个具有自己属性的表。子类将只有一个表,其属性具有(或添加),就像继承属性以外的属性一样。继承的属性将映射到父表,并以唯一的id链接到。
不知道这是不是你想要的答案,但我会这么看。
https://stackoverflow.com/questions/11019847
复制相似问题