为什么 SQL 在删除引用时无法删除父行

why SQL cannot delete parent row when references are deleted

我创建了一个包含一些 table 的数据库,它们相互关联。但问题是我可以从子 table 中删除记录,但不能从父 table.

中删除记录

查看我的SQL表结构代码

User:

CREATE TABLE "User"
(
    ID INT generated by default as identity PRIMARY KEY,
    username varchar(55) NOT NULL,
    password varchar(65) NOT NULL,
    "role" varchar(65) NOT NULL
);

Activity:

CREATE TABLE Activity
(
    ID INT generated by default as identity PRIMARY KEY,
    "time" varchar(55) NOT NULL,
    "date" varchar(55) NOT NULL,
    purgedDocumentName varchar(55) NOT NULL,
    user_ID INTEGER,
    CONSTRAINT fk_activity_usr FOREIGN KEY (user_ID)
    REFERENCES EDMSDATABASE."User"(ID)
);

Message:

CREATE TABLE Message
(
    ID INT generated by default as identity PRIMARY KEY,
    title varchar(255) NOT NULL,
    subject varchar(255) NOT NULL,
    description varchar(255) NOT NULL,
    deadline varchar(255) NOT NULL
);


WorkflowMessage:

CREATE TABLE WorkflowMessage
(
    user_ID INTEGER ,
    message_ID INTEGER ,
    CONSTRAINT fk_usr_user FOREIGN KEY (user_ID)
    REFERENCES EDMSDATABASE."User"(ID),

    CONSTRAINT fk_usr_msg FOREIGN KEY (message_ID)
    REFERENCES EDMSDATABASE.Message(ID)
);


Document:

CREATE TABLE Document
(
    ID INT generated by default as identity PRIMARY KEY,
    "name" varchar(255) NOT NULL,
    description varchar(255) NOT NULL,
    location varchar(255) NOT NULL,
    createdDate varchar(255) NOT NULL,
    status varchar(255) NOT NULL,
    user_ID INTEGER ,

    CONSTRAINT fk_doc_user FOREIGN KEY (user_ID)
    REFERENCES EDMSDATABASE."User"(ID)
);


Version:

CREATE TABLE Version
(
    ID INT generated by default as identity PRIMARY KEY,
    versionNumber INTEGER NOT NULL,
    mofiedDate varchar(255) NOT NULL,
    newLocation varchar(255) NOT NULL,
    document_ID INTEGER ,

    CONSTRAINT fk_doc_version FOREIGN KEY (document_ID)
    REFERENCES EDMSDATABASE.Document(ID)
);


Trash

CREATE TABLE RemovedDocument
(
    ID INTEGER PRIMARY KEY,
      FOREIGN KEY (ID) REFERENCES EDMSDATABASE.Document(ID),
    newLocation VARCHAR(255)
);



Historical Document

CREATE TABLE HistoricalDocument
(
    ID INTEGER PRIMARY KEY,
      FOREIGN KEY (ID) REFERENCES EDMSDATABASE.Document(ID),
    newLocation VARCHAR(255),
    retentionDate VARCHAR(12)
);


Group

CREATE TABLE "Group"
(
    "rights" INTEGER NOT NULL,
    user_ID INTEGER ,
    document_ID INTEGER ,
    CONSTRAINT fk_group_document FOREIGN KEY (document_ID)
    REFERENCES EDMSDATABASE.DOCUMENT(ID),

    CONSTRAINT fk_group_usr FOREIGN KEY (user_ID)
    REFERENCES EDMSDATABASE."User"(ID)
);

您可以从子 table 中删除行但不能从父 table 中删除行的原因是您添加到子 [=48] 的 referential integrity =]s 当您在子 tables 中添加外键时引用父 tables.

中的主键

例如,要从 table User 中删除带有键 ID = 1 的行,您首先需要删除外键 user_ID = 1 所在的所有行在接下来的 table 中:

  • Activity
  • 工作流消息
  • 文档

作为手动删除子行的替代方法,您可以使用 ON DELETE CASCADE 重新定义外键,即:

CREATE TABLE Activity
(
    ID INT generated by default as identity PRIMARY KEY,
    ... other columns
    user_ID INTEGER,
    CONSTRAINT fk_activity_usr FOREIGN KEY (user_ID)
    REFERENCES EDMSDATABASE."User"(ID) ON DELETE CASCADE  -- Cascading delete
);

这里会发生的情况是,如果引用的父 User.ID 行被删除,则 table Activity 中链接的所有子行都将被删除。 (您需要为所有引用 User.Id 的子 table 重复上述操作)请谨慎使用此选项!

另一种方法是在子table中允许外键为null,然后在外键中指定ON DELETE SET NULL

CREATE TABLE Activity
(
    ID INT generated by default as identity PRIMARY KEY,
    ... other columns
    user_ID INTEGER NULL, -- Nullable
    CONSTRAINT fk_activity_usr FOREIGN KEY (user_ID)
    REFERENCES EDMSDATABASE."User"(ID) ON DELETE SET NULL
);

与级联删除一样,如果父 User.Id 行被删除,则 Activity 中的所有引用子行都将 UserId 更新为 NULL(但未删除) .同样,请谨慎使用这种方法,因为这会导致子行成为孤立行。