MS SQL是否使用ON DELETE CASCADE选项限制自引用约束? 我有一个父子关系表,PARENT_ID列是ID的外键。使用ON DELETE CASCADE选项创建它会导致错误
“引入FOREIGN KEY约束 可能导致循环或多个级联 路径。指定ON DELETE NO ACTION或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY约束。“
我无法相信我必须在递归模式下删除此层次结构。除了触发器有什么问题吗?
答案 0 :(得分:9)
无法在具有自引用约束的表上设置ON DELETE CASCADE。存在潜在的周期性逻辑问题,因此它不会允许它。
有一篇好文章here - 虽然它适用于版本8而不是9版SQL - 尽管适用相同的规则。
答案 1 :(得分:4)
我刚回答another question 这个问题被绑定为重复。我认为值得在这里提出我的答案:
这是不可能的。您可以使用INSTEAD OF TRIGGER
create table locations
(
id int identity(1, 1),
name varchar(255) not null,
parent_id int,
constraint pk__locations
primary key clustered (id)
)
GO
INSERT INTO locations(name,parent_id) VALUES
('world',null)
,('Europe',1)
,('Asia',1)
,('France',2)
,('Paris',4)
,('Lyon',4);
GO
- 此触发器将使用递归CTE获取您要删除的所有ID之后的所有ID。这些ID将被删除。
CREATE TRIGGER dbo.DeleteCascadeLocations ON locations
INSTEAD OF DELETE
AS
BEGIN
WITH recCTE AS
(
SELECT id,parent_id
FROM deleted
UNION ALL
SELECT nxt.id,nxt.parent_id
FROM recCTE AS prv
INNER JOIN locations AS nxt ON nxt.parent_id=prv.id
)
DELETE FROM locations WHERE id IN(SELECT id FROM recCTE);
END
GO
- 在此测试,尝试使用不同的ID。您也可以尝试WHERE id IN(4,3)
...
SELECT * FROM locations;
DELETE FROM locations WHERE id=4;
SELECT * FROM locations
GO
- 清理(仔细查看真实数据!)
if exists(select 1 from INFORMATION_SCHEMA.TABLES where TABLE_NAME='locations')
---DROP TABLE locations;
答案 2 :(得分:0)
CREATE TRIGGER MyTable_OnDelete ON MyTable
INSTEAD OF DELETE
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM mt
FROM deleted AS D
JOIN MyTable AS mt
ON d.Id = mt.ParentId
DELETE FROM mt
FROM deleted AS D
JOIN MyTable AS mt
ON d.Id = mt.Id
END