web-dev-qa-db-ja.com

テーブル 'X'にFOREIGN KEY制約 'FK_X_Y'を導入すると、サイクルまたは複数のカスケードパスが発生する可能性があります

そのため、Visual Studioでデータベーススクリプトを発行しているときに、次のエラーが発生します:テーブル 'Users'にFOREIGN KEY制約 'FK_Users_Manager'を導入すると、サイクルまたは複数のカスケードパスが発生する場合があります。 ON DELETE NO ACTIONまたはON UPDATE NO ACTIONを指定するか、他のFOREIGN KEY制約を変更します。

これは、自己参照ユーザーテーブルを作成するための簡単なスクリプトです。

CREATE TABLE [dbo].[Users]
(
    [UserId] INT NOT NULL IDENTITY,
    [ManagerId] INT NULL,
    [Data] NVARCHAR(1024) NULL,
    CONSTRAINT [PK_Users_UserID] PRIMARY KEY ([UserId] ASC),
    CONSTRAINT [FK_Users_Manager] FOREIGN KEY ([ManagerId]) REFERENCES [Users] ([UserId]) ON DELETE SET NULL
)

どういうわけか私がこれらの関係を循環させたとしても、行のdirect子がManagerIdをNULL

このシナリオのトリガーを作成して、代わりにNULLsを設定する必要がありますか?それとも私が明らかに欠けているものはありますか?

1
Julius Rupšys

ここでINSTEAD OFトリガーを使用するか、ユーザーを削除する前にすべての直属部下を再割り当てするロジックを使用できます。例えば

--drop table if exists users
go
CREATE TABLE [dbo].[Users]
(
    [UserId] INT NOT NULL,
    [ManagerId] INT NULL,
    [Data] NVARCHAR(1024) NULL,
    CONSTRAINT [PK_Users_UserID] PRIMARY KEY ([UserId] ASC),
    CONSTRAINT [FK_Users_Manager] FOREIGN KEY ([ManagerId]) REFERENCES [Users] ([UserId]) ON DELETE NO ACTION
)

go
create trigger tg_users_del on [Users] instead of delete
as
begin
  set nocount on;
  update Users set ManagerId = null where ManagerId in (select UserID from deleted);
  delete from Users where UserId in (select UserID from deleted);
end

GO
INSERT INTO Users(UserId, ManagerId) values (1,null),(2,1),(3,1),(4,2)

DELETE FROM Users where UserId = 1

select * from Users