我有两张桌子:
// Person.Details Table:
PersonID int [PK] | EmployeeCreatorID int [FK] | FirstName varchar | OtherInfo...
// Employee.Details Table:
EmployeeID int [PK] | PersonID int [FK] | IsAdmin bit | OtherInfo...
每个表都与另一个表相关:
[Employee.Details.PersonID]===>[Person.Details.PersonID] AND
[Person.Details.EmployeeCreatorID]===>[Employee.Details.EmployeeID]
通过他们的外键。
问题是,如果不删除其中一个外键约束,插入行,然后再添加约束(这是非常蹩脚的),就无法创建第一个人/员工。
这里显而易见的上帝悖论是第一个“员工”不存在来创造自己(“人”)。
有没有办法同时将数据插入两个表?这个创建的创建者场景只需要发生一次。如果我不能同时将数据插入两个表中,那么你还有其他任何方法吗?
澄清
还有其他与“人物”表相关的表格......如“学生”和“监护人”。一个人不能切换类型(员工不能切换到学生或监护人,反之亦然)。矛盾类似于具有ManagerID FK的Employee表;除了我的情况,表格已经分开了。
解 感谢Remus Rusanu和b0fh
--/*seeds database with first employee*/
BEGIN TRAN
GO
INSERT INTO Person.Details
(EmployeeCreatorID, FirstName, Active)
VALUES
(@@Identity, 'Admin', 1)
DECLARE @Identity int;
SET @Identity = @@Identity;
INSERT INTO Employee.Details
(PersonID, IsAdmin, Email, Password)
VALUES
(@Identity, 1, 'admin', 'admin')
UDPATE
Person.Details
SET
EmployeeCreatorID = @@Identity
WHERE
PersonID = @Identity
IF(@@ERROR <> 0)
ROLLBACK TRAN
ELSE
COMMIT TRAN
答案 0 :(得分:3)
NULL键将传递外键约束。你可以插入一个具有NULL CreatorID的Person,这将成为整个层次结构的大爸爸。
您还可以插入禁用约束,插入指向彼此的第一对(Person,Employee),然后启用约束,从现在开始系统播种。
答案 1 :(得分:2)
不确定SQL服务器,但在我知道的其他DBMS中,只要这两个步骤在单个事务中,就可以执行。只需在BEGIN;
和COMMIT;
之间包含两个语句。
答案 2 :(得分:1)
我宁愿改变数据库设计。表格不应该以这种方式相关联。
答案 3 :(得分:0)
模型对我来说是有缺陷的,但我认为你可能只需要更好地解释这些要求。到目前为止:
是否有员工不是员工?他们为什么在系统中?一个人是否有可能从员工转为非员工,反之亦然?
虽然我认为当你可以回答上述问题时可能会有更好的答案。一个建议就是将EmployeeCreaterId更改为PersonCreatorId,并且具有PersonCreatorId是雇员的辅助(不强制通过数据库模式)要求。
答案 4 :(得分:0)
您只需要有一名员工来创建可能是或可能不是员工的人员。唯一的问题是员工无法创造自己。所以我建议在进入数据库的第一个人之前确保employeecreatorid fk不是必需的列。 然后创建这个人。 然后为该相关人员创建员工记录。由于您有一个人,您可以在employee表中要求personID FK并且它将存在。 然后更新原始Person记录设置EmployeeCreatorId等于新创建的EmployeeID 接下来,将person表中的EmployeeCreatorID FK列设置回所需的值 现在,您必须确保只有当前员工创建任何新员工,而当前员工不会是正在创建的人员。
这将避免每次创建新人时都需要删除和重新创建密钥。祝你好运。