您使用什么样的sql技巧将数据输入到两个表中,其中包含循环引用。
Employees
EmployeeID <PK>
DepartmentID <FK> NOT NULL
Departments
DepartmentID <PK>
EmployeeID <FK> NOT NULL
员工属于某个部门,部门必须有经理(部门主管)。
我是否必须禁用插入的约束?
答案 0 :(得分:13)
我假设您的Departments.EmployeeID是部门负责人。我要做的是让那个列可以为空;然后你可以先创建部门,然后创建员工。
答案 1 :(得分:5)
问:我是否必须禁用插件的约束?
答:在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;
让我们打开那个:
注意:禁用外键约束对所有会话生效,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
[/编辑]
答案 2 :(得分:3)
这个问题可以用可取的约束来解决。提交整个事务时会检查此类约束,从而允许您在同一事务中插入员工和部门,并相互引用。 (假设数据模型有意义)
答案 3 :(得分:1)
通过删除循环引用来重构模式 从任一表模式中删除ID列。
在我看来,Departments.EmployeeID 似乎不属于那里。
答案 4 :(得分:1)
我无法想到这样做的非hackish方式。我认为你需要删除约束或做一些在所有插入后更新的傻虚拟值。
我建议重构数据库架构。我想不出你为什么要这样工作的原因。
也许像Employee,EmployeeDepartment(EmployeeId,DepartmentId)和Department这样可以更好地实现同样的目标。
答案 5 :(得分:1)
你可以在Department表中为'Unassigned'
创建一行要使用新员工创建新部门,您可以
这不会使您当前的架构失效,您可以设置一个定期运行的任务,以检查是否没有未分配部门的成员。
您还需要创建一个默认员工作为未分配的员工
编辑:
混乱提出的解决方案虽然简单得多,但
答案 6 :(得分:1)
我使用过一些好的设计。所有这些都涉及从Department表中删除“manager”EmployeeID并从Employee表中删除DepartmentID。我已经看到了几个提到它的答案,但我会澄清我们如何使用它:
我通常最终得到一个EmployeeDepartment关系链表 - 多对多,通常带有IsManager,IsPrimaryManager,IsAdmin,IsBackupManager等标志,它们澄清了一些可能受到限制的关系,因此每个只允许一个主管理器部门(虽然一个人可以是多个部门的PrimaryManager)。如果您不喜欢单个表,那么您可以拥有多个表:EmployeeDepartment,ManagerDepartment等,但是您可能会遇到一个人是经理但不是员工的情况等。
我们通常也允许人们成为多个部门的成员。
为简化访问,您可以提供适当执行连接的视图。
答案 7 :(得分:0)
是的,在这种情况下,您必须禁用外键。
答案 8 :(得分:0)
您需要永久删除一个或另一个参考。这不是一个可行的设计结构。哪个必须先进入?部门还是员工?除非你的部门都是一个大员工,否则结构就没有意义,因为每个员工都必须有明显的离职。