数据库设计模式,其中一个属性仅适用于另一个属性具有特定值的情况

Ash*_*ine 1 sql database-design naming design-patterns

我经常看到这种设计模式,但没有它的名称.我很想知道设计师称这种模式什么,以及他们如何通过合理的数据库设计来实现它.

举个简单的例子,假设学生有一个年级(1-8).如果学生的成绩为7或8,那么他们可能是荣誉学生.那么你如何跟踪学生的这个位旗,知道它只适用于某些年级的学生?

Dan*_*ons 5

我称之为数据依赖.并非所有数据依赖关系都可以通过关系分解直接或方便地建模.使用检查约束可以很容易地处理这个:

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))
);
Run Code Online (Sandbox Code Playgroud)

另一种解决方案可能是使用两个表:

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)
);
Run Code Online (Sandbox Code Playgroud)

这种替代设计更清楚地表明了等级与是否有荣誉标志之间的关系,并为7-8级学生的进一步差异留下了空间(尽管表名应该改进).如果你只有一个属性,荣誉布尔值,那么这可能是矫枉过正.正如@BrankoDimitrijevic所提到的那样,这并不是Honors因为等级是7或8 而强制存在一行,而且你还要支付你不需要的索引.所以有权衡; 这些肯定不是唯一可能的两个设计; 布兰科还建议使用触发器.

在OO设计方面,@ Ryan是正确的,但对于正确的关系数据库设计,通常不会通过尝试识别继承模式来解决问题.这就是面向对象的观点.关注您的访问模式以及您的代码将如何获取数据始终是非常重要的,但在关系数据库设计中,首先要求数据库中的规范化和灵活性,以及​​第二个代码,因为总是会有多个代码库获取数据,并且您希望确保数据始终有效,无论访问代码有多么多.