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

时间:2015-04-13 15:37:44

标签: sql derby

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

请参阅我的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)
);

1 个答案:

答案 0 :(得分:3)

您可以从子表中删除行而不是从父表中删除行的原因是,当您在引用主键的子表中添加外键时,您添加到子表的referential integrity在父表中。

例如,为了使用键User从表ID = 1中删除行,您首先需要删除下表中外键user_ID = 1的所有行: / p>

  • 活动
  • WorkflowMessage
  • 文档

作为手动删除子行的替代方法,您可以做的是使用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行,则删除表Activity中链接的所有子行。 (您需要对引用User.Id的所有子表重复上述操作。)谨慎使用此选项!

另一种方法是允许外键在子表中为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(但不会删除)。同样,要小心这种方法,因为这会导致子行成为孤儿。