SQL Server:具有使用级联删除自身的外键的表

use*_*784 5 t-sql sql-server

我需要一个表格表格来保存像这样的层次结构树数据(即大陆,国家,城市)

id  name    parent
-------------------
1   world   null
2   Europe  1
3   Asia    1
4   France  2
5   Paris   4
6   Lyon    4
Run Code Online (Sandbox Code Playgroud)

我要删除France,希望该表可以级联删除所有法国城市。但是当我像这样创建表时

create table locations 
(
    id int identity(1, 1),
    name varchar(255) not null,
    parent_id int,

    constraint pk__locations
        primary key clustered (id),

    constraint fk__locations
        foreign key (parent_id) 
            references locations (id)
                on delete cascade
                on update no action 
)
Run Code Online (Sandbox Code Playgroud)

我有一个错误

在表“位置”上引入外键约束“ fk__locations”可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。

信息说

  1. 指定ON DELETE NO ACTION-这正是我想要的
  2. 指定ON UPDATE NO ACTION-指定
  3. 修改其他FOREIGN KEY约束-我不明白

有人可以帮忙吗?

Shn*_*ugo 5

这不可能。你可以用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
Run Code Online (Sandbox Code Playgroud)

-- 此触发器将使用递归 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
Run Code Online (Sandbox Code Playgroud)

--在这里测试,尝试不同的ID。你也可以试试WHERE id IN(4,3)...

SELECT * FROM locations;

DELETE FROM locations WHERE id=4;

SELECT * FROM locations
GO
Run Code Online (Sandbox Code Playgroud)

--清理(小心真实数据!)

if exists(select 1 from INFORMATION_SCHEMA.TABLES where TABLE_NAME='locations')
---DROP TABLE locations;
Run Code Online (Sandbox Code Playgroud)