递归删除触发器和ON DELETE CASCADE约束不会删除所有内容

时间:2011-11-26 07:56:32

标签: database tsql database-design recursion triggers

我有一个非常简单的数据模型,代表树结构:

RootEntity是此类树的根,它可以包含ContainerEntity类型和AtomEntity类型的子项。类型ContainerEntity也可以包含ContainerEntity类型和AtomEntity类型的子项,但不能包含RootEntity类型的子项。儿童以众所周知的顺序被引用。数据库模型如下所示。

我现在的问题是当我删除RootEntity时,我想要递归删除所有孩子。我用CASCADE DELETE创建了外键,为此创建了两个删除触发器。但它并没有删除所有内容,它总是在ContainerEntityAtomEntityContainerEntity_ChildrenAtomEntity_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

1 个答案:

答案 0 :(得分:1)

尝试没有触发器:

Entity
Id 
Name
PRIMARY KEY (id)

ParentEntity                  --- Root or Container
Id 
PRIMARY KEY (id)
FOREIGN KEY (Id) REFERENCES Entity (Id)
            ON DELETE CASCADE

ChildEntity                   --- Container or Atom
Id
ParentId
OrderIndex 
PRIMARY KEY (Id)
UNIQUE KEY (ParentId, OrderIndex)
FOREIGN KEY (Id) REFERENCES Entity (Id)
            ON DELETE CASCADE
FOREIGN KEY (ParentId) REFERENCES ParentEntity (Id)
            ON DELETE CASCADE

其余的:

RootEntity
Id 
PRIMARY KEY (Id)
FOREIGN KEY (Id) REFERENCES ParentEntity (Id)         --- it is a Parent
            ON DELETE CASCADE

ContainerEntity
Id 
PRIMARY KEY (Id)
FOREIGN KEY (Id) REFERENCES ParentEntity (Id)         --- it is a Parent
            ON DELETE CASCADE
FOREIGN KEY (Id) REFERENCES ChildEntity (Id)          --- and a Child
            ON DELETE CASCADE

AtomEntity
Id
PRIMARY KEY (Id)
FOREIGN KEY (Id) REFERENCES ChildEntity (Id)          --- it is a Child
            ON DELETE CASCADE