3

我有两张表有点像这样:

// 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]

通过他们的外键。

问题是,如果不删除一个外键约束、插入行,然后重新添加约束(这很蹩脚),就不可能创建第一个人/员工。

这里明显的上帝悖论是第一个“员工”并不是为了创造自己(“人”)而存在的。

有没有办法同时将数据插入两个表?这个 created-is-the-creator 场景只需要发生一次。如果我不能同时将数据插入两个表中,您的天才们还有其他方法建议吗?

澄清

还有其他表与“Persons”表相关……例如“Students”和“Guardians”。一个人不能切换类型(员工不能切换到学生或监护人,反之亦然)。这个悖论类似于具有 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
4

5 回答 5

3

NULL 键将通过外键约束。您可以插入一个具有 NULL CreatorID 的 Person,这将成为整个层次结构的祖父。

您还可以插入禁用约束,插入指向彼此的第一对 (Person, Employee),然后重新启用约束并从现在开始为系统播种。

于 2010-02-25T00:05:09.503 回答
2

不确定 SQL 服务器,但在我知道的其他 DBMS 中,只要这两个步骤在一个事务中,你就可以做到。只需将两个语句包装在BEGIN;和之间COMMIT;

于 2010-02-25T00:01:03.767 回答
1

我宁愿改变数据库设计。表格不应该以这种方式关联,恕我直言。

于 2010-02-25T00:04:28.737 回答
0

模型在我看来有缺陷,但我认为您可能只需要更好地解释要求。至今:

  • 每个人都是由员工创建的。
  • 员工是一个人。

有不是员工的人吗?为什么他们在系统中?一个人是否有可能从员工转变为非员工,反之亦然?

虽然我认为当您可以回答上述问题时可能会有更好的答案。一个建议是将 EmployeeCreaterId 更改为 PersonCreatorId,并有一个次要(不是通过数据库模式强制执行)要求 PersonCreatorId 是员工。

于 2010-02-25T00:02:57.937 回答
0

您只需拥有一名员工即可创建可能是也可能不是员工的人。唯一的问题是员工无法创造自己。所以我建议在将第一个人输入数据库之前确保employeecreatorid fk 不是必需的列。然后创建人。然后为该相关人员创建员工记录。由于您有一个人,您可以在员工表中要求 personID FK 并且它将存在。然后更新原始的 Person 记录,将 EmployeeCreatorId 设置为新创建的 EmployeeID 接下来,将 person 表中的 EmployeeCreatorID FK 列设置回必需。
现在,您必须确保任何新人都仅由当前员工创建,而不是被创建的人。

这将避免每次创建新人时都需要删除和重新创建密钥。祝你好运。

于 2010-02-25T02:09:00.377 回答