Employees EmployeeID <PK> DepartmentID <FK> NOT NULL Departments DepartmentID <PK> EmployeeID <FK> NOT NULL
员工属于某个部门,部门必须有经理(部门主管).
我是否必须禁用插入的约束?
解决方法
答:在Oracle中,不,如果外键约束是DEFERRABLE则不行(参见下面的示例)
对于Oracle:
SET CONSTRAINTS ALL DEFERRED; INSERT INTO Departments values ('foo','dummy'); INSERT INTO Employees values ('bar','foo'); UPDATE Departments SET EmployeeID = 'bar' WHERE DepartmentID = 'foo'; COMMIT;
我们解压一下:
>(自动提交必须关闭)
>延迟执行外键约束
>在Department表中插入一行,其中FK列的“哑”值
>使用FK引用部门向Employee表插入一行
>使用实际参考替换Department FK中的“dummy”值
>重新启用约束的执行
注意:禁用外键约束对所有会话生效,DEFERRING约束处于事务级别(如示例中)或会话级别(ALTER SESSION SET CONSTRAINTS = DEFERRED;)
Oracle允许将外键约束定义为DEFERRABLE至少十年.我定义所有外键约束(当然)是可以直接推断的.这保持了每个人所期望的默认行为,但允许操作而不需要禁用外键.
见AskTom:http://www.oracle.com/technology/oramag/oracle/03-nov/o63asktom.html
见AskTom:http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:10954765239682
另见:http://www.idevelopment.info/data/Oracle/DBA_tips/Database_Administration/DBA_12.shtml
[编辑]
答:在Microsoft sql Server中,您无法像在Oracle中那样推迟外键约束.禁用和重新启用外键约束是一种方法,但我对1)性能影响(在重新启用约束时检查ENTIRE表的外键约束)的前景感到不寒而栗,2)处理异常如果(何时?)重新启用约束失败.请注意,禁用约束将影响所有会话,因此在禁用约束时,其他会话可能会插入和更新将导致约束重新启用失败的行.
使用sql Server,更好的方法是删除NOT NULL约束,并在插入/更新行时允许NULL作为临时占位符.
对于sql Server:
-- (with NOT NULL constraint removed from Departments.EmployeeID) insert into Departments values ('foo',NULL) go insert into Employees values ('bar','foo') go update Departments set EmployeeID = 'bar' where DepartmentID = 'foo' go
[/编辑]