表的唯一目的是指定另一个表的子集

时间:2014-11-27 20:54:29

标签: mysql database-design subset subtyping

我正在设计的数据库有一个employees表;可以有多种类型的员工,其中一种是医疗员工。数据库还需要描述医疗员工之间的多对多关系以及他们的能力。

是否可以创建仅包含medical_employees列的表id,其唯一目的是指定哪些员工是医务人员? id列具有引用employees表的外键约束。下面的代码应该让我的问题更清楚:

/* Defines a generic employee */
CREATE TABLE employees (
    id      INT PRIMARY KEY AUTO_INCREMENT,
    name    VARCHAR(100) NOT NULL
);

/* Specifies which employees are medics */
CREATE TABLE medical_employees (
    id INT NOT NULL,
    FOREIGN KEY (id) references employees(id);
);

/* Specifies what competences a medic can have */
CREATE TABLE medical_competences (
    id     INT PRIMARY KEY AUTO_INCREMENT,
    name   VARCHAR(100) NOT NULL
);

/* A many-to-many relation between medical employees and
   their competences. */
CREATE TABLE medical_employees_competences (
    id             INT PRIMARY KEY AUTO_INCREMENT,
    medic_id       INT NOT NULL,
    competence_id  INT NOT NULL,
    FOREIGN KEY (medic_id) REFERENCES medical_employees(id),
    FOREIGN KEY (competence_id) REFERENCES medical_competences(id)
);

3 个答案:

答案 0 :(得分:1)

为什么要有一个单独的表格。为什么不创建一个BIT/Boolean字段说IsMedical并将其设置为TRUE,以便employee表中的医疗员工

/* Defines a generic employee */
CREATE TABLE employees (
    id      INT PRIMARY KEY AUTO_INCREMENT,
    name    VARCHAR(100) NOT NULL,
    IsMedical BIT(1)
);

那就是说,如果你想从Employee表中获得所有医务人员;您只需在WHERE条件下执行单个过滤器WHERE IsMedical = true。然而,如果您通过单独的表格进行操作,那么您将使用INNER JOINmedical_employees表执行employees,我相信这样会更加昂贵且不必要。

答案 1 :(得分:1)

+1从@Rahul回答,另一种方法是在employees表中创建一个属性。虽然我不会使用BIT,因为该数据类型存在错误。只需使用BOOLEAN或TINYINT。

但是你创建第二个表的方式有以下优点:medical_employees_competences被隐含地限制为仅引用医疗员工。它不能引用某人,除非他们在该表中。

提供该约束的另一种方法是以下列方式创建外键:

CREATE TABLE employees (
    id      INT PRIMARY KEY AUTO_INCREMENT,
    name    VARCHAR(100) NOT NULL
    IsMedical BOOLEAN DEFAULT 0,
    KEY (id, IsMedical)
);

/* A many-to-many relation between medical employees and
   their competences. */
CREATE TABLE medical_employees_competences (
    id             INT PRIMARY KEY AUTO_INCREMENT,
    IsMedical      BOOLEAN DEFAULT 1, /* only put 1 in this column */
    medic_id       INT NOT NULL,
    competence_id  INT NOT NULL,
    FOREIGN KEY (medic_id, IsMedical) REFERENCES medical_employees(id, IsMedical),
    FOREIGN KEY (competence_id) REFERENCES medical_competences(id)
);

现在您可以实现相同的约束,您只能使用第二个表来引用医务人员。

答案 2 :(得分:1)

是的,没关系,这是直截了当的关系成语,这是你应该做的。 (您可以搜索SQL子类型和超类型。)

当一个人有一个不相交的子类型时,例如员工只能属于一种类型的其他类型的员工,就会有尽可能以声明的方式限制这种情况的SQL惯用语。这可能涉及超类型中的常量类型鉴别器列,描述其id应该出现在哪个唯一子类型中。(IDEF1X成语。)还有一个成语涉及该类型鉴别器也在子类型中有时避免进一步的非声明性约束。前者见(答案)How to Implement Referential Integrity in Subtypes。 (解释前者虽然贬低后者。)后者见(会议文件)Foreign Superkeys and Constant References