当ER图中有一个参与约束,如何表达?(奶牛书3.5.4)

2019-09-28  本文已影响0人  Divenier

ER图如图所示:


er.jpg

1.将参与的实体和联系两者共同放入一个表中(只有同时具有码约束和参与约束时才能如此解决)

CREATE TABLE Dep_Mgr ( did INTEGER,
    dname CHAR(20) ,
    budget REAL,
    ssn CHAR(11) NOT NULL,
    since DATE,
    PRIMARY KEY (did),
    FOREIGN KEY (ssn) REFERENCES Employees
ON DELETE NO ACTION)

原书:

上面的SQL语句不允许属性ssn的值为null,这样,Dept_Mgr的每条记录也就都能确定Employees中的一条记录(经理),可以满足每个部门都有经理的参与约束。语句中的NOACTION确保被Dept_Mgr引用了的Employees记录不会被删除,而且这也是默认的操作,可以不用明确给出。如果我们希望删除这条Employees记录,那么需要在删除前修改相应的Dept_Mgr记录,使一个新的雇员成为经理

疑问:为什么不能使用直接创建Manages表,简单的在did、SSN后加上NOT NULL呢?(如下语句)

CREATE TABLE manages(
    SSN CHAR(11) NOT NULL,
    did INTERGER NOT NULL,
    since DATE,
    PRIMARY KEY(did),//不存在did相同ssn不同的情况
    FREIGN KEY (SSN) REFERENCE (employee),
    FREIGN KEY (did) REFERENCE (Department))

因为:单独创建Manages表无法表达参与约束,Manages表确实表示了“SSN不能为空”即——必须有经理——这件事,但是Manages是个关系,而并不是所有Departments都确定有这个关系

原书中是这样解释的:

对于每个部门都必须有经理的约束,无法使用3.5.3节讨论的第一种方法来转换(对于前面定义的Manages,如果对字段ssn和did添加NOTNULL约束,将产生什么样的效果呢?提示:该约束将防止解雇一个经理,但是不能确保开始时每个部门都有经理)。
因此,我们只能使用第二种方法来转换一对多的联系集,如Manages,尤其是具有码约束同时又具有全参与约束的实体集。

文中提到的“第二种方法”即,把Departments和Manages关系放到一起创建表的方法

书中对此方法这样评价:

事实上,对于前面有关Manages联系集的示例,可以看成用码和外码约束来表达参与约束的一个范例。Manages是一个二元联系集,其中一个实体集(Departments)具有码约束,并且该实体集还需要满足完全参与约束。

Q:为什么只有同时具有码约束时才能如此解决?

我们的方法是,将实体Department和manage关系结合了,因此,一个Department实体自然只能有一个manager,此处,manage的关系对于Department就像拥有的一个属性一样,当然只能有一个,也就是必须满足码约束。

2.在使用SQL时定义断言(完全参与)

ER图同上,原文:

为保证Works_In中的Departments的完全参与,在使用SQL时我们需要定义一个断言,要求Departments中的每个did值都出现在Works_ln的某个记录;并且对于Works_In中指向其他实体集的外码字段(如在本例中的字段ssn),其值不允许为null。
通过强制要求Works_In的ssn字段值不能为null,可以确保约束的第二部分得到满足(即确保Employees在Works_In中的参与是对称的)。

create assertion must_dep
check((select count(*)
    from tb_dep_mgr d
    where d.did not in(select w.did
                from tb_works_in w) =0)

笔者在oracle 11g中尝试运行该语句,随后就发现oracle并不支持断言的声明……因此上段代码的正确性无法保证,做个参考吧。

上一篇下一篇

猜你喜欢

热点阅读