У меня есть очень простая модель данных, которая представляет древовидную структуру:
RootEntity
является корнем такого дерева, оно может содержать дочерние элементы типа ContainerEntity
и типа AtomEntity
. Тип ContainerEntity
также может содержать дочерние элементы типа ContainerEntity
и типа AtomEntity
, но не может содержать дочерние элементы типа RootEntity
. На детей ссылаются в хорошо известном порядке. Модель БД для этого приведена ниже.
Моя проблема в том, что когда я удаляю RootEntity
, я хочу, чтобы все дочерние элементы были удалены рекурсивно. У меня есть внешний ключ с CASCADE DELETE и два триггера удаления для этого. Но он не удаляет все, он всегда оставляет некоторые элементы в таблицах ContainerEntity
, AtomEntity
, ContainerEntity_Children
и AtomEntity_Children
. Кажется, начиная с уровня рекурсии 3.
CREATE TABLE RootEntity
(
Id UNIQUEIDENTIFIER NOT NULL,
Name VARCHAR(500) NOT NULL,
CONSTRAINT PK_RootEntity PRIMARY KEY NONCLUSTERED (Id),
);
CREATE TABLE ContainerEntity
(
Id UNIQUEIDENTIFIER NOT NULL,
Name VARCHAR(500) NOT NULL,
CONSTRAINT PK_ContainerEntity PRIMARY KEY NONCLUSTERED (Id),
);
CREATE TABLE AtomEntity
(
Id UNIQUEIDENTIFIER NOT NULL,
Name VARCHAR(500) NOT NULL,
CONSTRAINT PK_AtomEntity PRIMARY KEY NONCLUSTERED (Id),
);
CREATE TABLE RootEntity_Children
(
ParentId UNIQUEIDENTIFIER NOT NULL,
OrderIndex INT NOT NULL,
ChildContainerEntityId UNIQUEIDENTIFIER NULL,
ChildAtomEntityId UNIQUEIDENTIFIER NULL,
ChildIsContainerEntity BIT NOT NULL,
CONSTRAINT PK_RootEntity_Children
PRIMARY KEY NONCLUSTERED (ParentId, OrderIndex),
-- foreign key to parent RootEntity
CONSTRAINT FK_RootEntiry_Children__RootEntity
FOREIGN KEY (ParentId) REFERENCES RootEntity (Id)
ON DELETE CASCADE,
-- foreign key to referenced (child) ContainerEntity
CONSTRAINT FK_RootEntiry_Children__ContainerEntity
FOREIGN KEY (ChildContainerEntityId) REFERENCES ContainerEntity (Id)
ON DELETE CASCADE,
-- foreign key to referenced (child) AtomEntity
CONSTRAINT FK_RootEntiry_Children__AtomEntity
FOREIGN KEY (ChildAtomEntityId) REFERENCES AtomEntity (Id)
ON DELETE CASCADE,
);
CREATE TABLE ContainerEntity_Children
(
ParentId UNIQUEIDENTIFIER NOT NULL,
OrderIndex INT NOT NULL,
ChildContainerEntityId UNIQUEIDENTIFIER NULL,
ChildAtomEntityId UNIQUEIDENTIFIER NULL,
ChildIsContainerEntity BIT NOT NULL,
CONSTRAINT PK_ContainerEntity_Children
PRIMARY KEY NONCLUSTERED (ParentId, OrderIndex),
-- foreign key to parent ContainerEntity
CONSTRAINT FK_ContainerEntity_Children__RootEntity
FOREIGN KEY (ParentId) REFERENCES ContainerEntity (Id)
ON DELETE CASCADE,
-- foreign key to referenced (child) ContainerEntity
CONSTRAINT FK_ContainerEntity_Children__ContainerEntity
FOREIGN KEY (ChildContainerEntityId) REFERENCES ContainerEntity (Id)
ON DELETE CASCADE,
-- foreign key to referenced (child) AtomEntity
CONSTRAINT FK_ContainerEntity_Children__AtomEntity
FOREIGN KEY (ChildAtomEntityId) REFERENCES AtomEntity (Id)
ON DELETE CASCADE,
);
CREATE TRIGGER Delete_RootEntity_Children ON RootEntity_Children FOR DELETE
AS
DELETE FROM ContainerEntity WHERE Id IN (SELECT ChildContainerEntityId FROM deleted)
DELETE FROM AtomEntity WHERE Id IN (SELECT ChildAtomEntityId FROM deleted)
GO
CREATE TRIGGER Delete_ContainerEntiy_Children ON ContainerEntity_Children FOR DELETE
AS
DELETE FROM ContainerEntity WHERE Id IN (SELECT ChildContainerEntityId FROM deleted)
DELETE FROM AtomEntity WHERE Id IN (SELECT ChildAtomEntityId FROM deleted)
GO