自我参考表

时间:2014-08-06 16:59:24

标签: sql sql-server self-join

我是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); --> 

引发以下错误

  

Msg 547,Level 16,State 0,Line 530
  INSERT语句与FOREIGN KEY约束冲突" FK_SELFREFE"。冲突发生在数据库" SARA",表" dbo.EMPLOYEES",栏目' EMPID'。

我做错了什么,这里?

1 个答案:

答案 0 :(得分:2)

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

编辑:回应评论:我不知道如何使自我引用ON DELETE SET NULL约束工作,但我认为你可以通过创建一个AFTER DELETE触发器来完成相同的目标,该触发器将MGRID设置为NULL 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。

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

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