【问题标题】:Self reference to the table表的自我参考
【发布时间】:2014-09-29 17:19:31
【问题描述】:

我是 SQL Server 的新手。

我想引用下面相同的表格列,

CREATE TABLE JOIN_DEPARTMENTS
(
  DEPTID INT PRIMARY KEY,
  DEPTNAME VARCHAR(20)
);

CREATE TABLE JOIN_EMPLOYEES
(
  EMPID INT PRIMARY KEY,
  EMPNAME VARCHAR(20),
  MGRID INT,
  DEPTID INT FOREIGN KEY REFERENCES JOIN_DEPARTMENTS(DEPTID),
  CONSTRAINT FK_SELFREFE FOREIGN KEY (MGRID) REFERENCES EMPLOYEES(EMPID) ON DELETE SET NULL
);

INSERT INTO JOIN_DEPARTMENTS VALUES (100, 'BFS');
INSERT INTO JOIN_DEPARTMENTS VALUES (101, 'MELT');

INSERT INTO JOIN_EMPLOYEES VALUES(1, 'SARA', NULL, 100);  --> inserts fine
INSERT INTO JOIN_EMPLOYEES VALUES(2, 'SANTHOSH', 1, 100); --> 

抛出以下错误

消息 547,级别 16,状态 0,行 530
INSERT 语句与 FOREIGN KEY 约束“FK_SELFREFE”冲突。冲突发生在数据库“SARA”、表“dbo.EMPLOYEES”、列“EMPID”中。

我做错了什么,在这里?

【问题讨论】:

    标签: sql sql-server self-join


    【解决方案1】:

    您的约束引用了 EMPLOYEES,但您正在插入 JOIN_EMPLOYEES - 检查 EMPLOYEES 以确保 EMPID=1 存在,或修改您的约束以检查 JOIN_EMPLOYEES 而不是 EMPLOYEES

    编辑:回应评论:我不知道如何使自引用 ON DELETE SET NULL 约束起作用,但我认为您可以通过创建一个将 MGRID 设置为 NULL 的 AFTER DELETE 触发器来实现相同的目标已删除行的 MGRID = EMPID 的行。我不能完全测试这个,但我认为这会工作

    CREATE TRIGGER trJOIN_EMPLOYEE_AfterDel   ON  JOIN_EMPLOYEES   AFTER DELETE
    AS BEGIN
        SET NOCOUNT ON;
        UPDATE JOIN_EMPLOYEES SET MGRID = NULL
        WHERE MGRID IN (SELECT EMPID FROM deleted)
    END
    

    基本上它的作用是在处理完您的删除之后,但在事务被认为完成之前,它会返回并将引用最近删除的员工 ID 的任何 MGRID 设置为 NULL。

    请注意,微软有一些相关信息
    http://technet.microsoft.com/en-us/library/ms186973%28v=sql.105%29.aspx
    说“由单个 DELETE 或 UPDATE 触发的一系列级联引用操作必须形成不包含循环引用的树。”所以我认为你不会让自引用约束起作用。

    另请注意,您可能必须先删除部分或全部约束,然后才能创建该触发器,我认为这只是 INSTEAD OF DELETE 触发器发生冲突,但 AFTER DELETE 触发器可能与某些约束发生冲突- 再次,这里的经验不足以让我确定,试试看吧。

    【讨论】:

    • 你是对的。我删除了表并再次创建它开始出现以下错误。在这种情况下我们不能有'ON Delete'吗?消息 1785,级别 16,状态 0,第 512 行在表“JOIN_EMPLOYEES”上引入 FOREIGN KEY 约束“FK_SELFREFE”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。消息 1750,级别 16,状态 0,行 512 无法创建约束或索引。查看以前的错误。
    • 对不起,我不知道那个问题的答案,这不是我以前遇到过的情况:-(
    • @SaravanaSanthosh 这是您提出的问题的答案。我觉得你应该接受。对于新的错误,也许你应该准备新的问题?
    猜你喜欢
    • 2017-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-13
    • 1970-01-01
    • 2020-09-19
    相关资源
    最近更新 更多