表A的外键,一定是其他某个表B的主键或有UNIQUE声明的属性。
A的外键的值,一定是对应表B中相应的属性值。(空值除外)
方法1:属性名 类型 REFERENCES 表名 (属性名)
方法2:FOREIGN KEY (属性名) REFERENCE 表名 (属性名)
CREATE TABLE Studio( name CHAR(30) PRIMARY KEY, address VARCHAR(255), persC# INT REFERENCES MovieExec(cert#) );
CREATE TABLE Studio( name CHAR(30) PRIMARY KEY, address VARCHAR(255), presC# INT, FOREIGN KEY (persC#) REFERENCES MovieExec(cert#) );
设表A的外键,是表B的主键或UNIQUE。则,下面的四种情况出错:
1.A中插入的新元组(非空值),其外键不是B中的值
2.A中修改的新元组(非空值),其外键不是B中的值
3.删除B中的元组,其主键非空,且是A的外键
4.修改B中的元组的主键,且是A的外键
其中1,2一定不能违反。3,4可以有3种处理方法:
1.缺省原则:拒绝违反更新。
2.级联原则:如果把B中的主键删除,则删除对应A中的元组;如果修改B中的主键,也修改A中相应的外键
3.置空值原则:如果对B的主键的修改,影响到了A中的外键,则把A中的相应外键置空。
声明方法:
ON DELETE或ON UPDATE后面加上SET NULL或CASCADE
CREATE TABLE Studio( name CHAR(30) PRIMARY KEY, address VARCHAR(255), presC# INT REFERENCES MovieExec(cert#) ON DELETE SET NULL ON UPDATE CASCADE );
上面语句表示,删除时采用置空值原则,更新时采用级联原则。
如果有循环约束,比如表A{属性a unique}, B{属性b unique}。a是外键,引用b;且b是外键,引用a。则这是一个循环约束。不管以怎样的顺序插入都会违反外键约束。解决方法:
1.将两个插入动作组成一个事务
2.通知DBMS不用检查其约束,直到整个事务完成执行并要提交为止。
为做到第2点,可以使用如下语句:
约束后面加: DEFERRABLE(延迟)或NOT DEFERRABLE(非延迟 默认)
DEFERRBLE后面可以有INITIALLY DEFERRED(检查推迟到事务提交前执行),INITIALLY IMMEDIATE(立即执行检查 ??跟NOT DEFERRABLE区别??)
如果约束有名字,如MyConstraint可以用
SET CONSTRAINT MyConstraint DEFERRED; 设为延迟检查
SET CONSTRAINT MyConstraint IMMEDIATE; 设为立即检查
CREATE TABLE Studio( name CHAR(30) PRIMARY KEY, address VARCHAR(255), persC# INT UNIQUE REFERENCES MovieExec(cert#) DEFERRABLE INITIALLY DEFERRED );
原文:http://www.cnblogs.com/dplearning/p/4882980.html