【发布时间】:2010-02-24 23:55:53
【问题描述】:
我有两张表是这样的:
// 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
【问题讨论】:
-
永远不要使用@@identity。数据完整性非常糟糕的做法。您在 2008 年,因此请改用输出子句或 scope_identity(),。 @@identity 如果有人在您的表上放置了一个触发器,该触发器将插入到另一个具有标识列的表中,那么@@identity 将给出不正确的值,使用它是非常危险的。
-
+1 就我而言,我认为 SCOPE_IDENTITY() 将是最佳选择; OUTPUT 子句会略高于右上角吗?
标签: sql sql-server sql-server-2008 insert relational