如何从表和所有引用中删除数据? [关闭]

Posted

技术标签:

【中文标题】如何从表和所有引用中删除数据? [关闭]【英文标题】:How to delete a data from a table and all the references? [closed] 【发布时间】:2022-01-09 09:01:03 【问题描述】:

我需要从“Customer”表中删除一个消费者,并从“ContactDetails”、“Invoice”和“ServiceTicket”表中删除与他相关的所有数据。

这是表格:

CREATE TABLE ContactDetail (
    DetailID integer IDENTITY(1,1) PRIMARY KEY,
    FirstName varchar(40) NOT NULL,
    SurName varchar(40) NOT NULL,
    DoB date NOT NULL,
    Address01 varchar(80) NOT NULL,
    Address02 varchar(80),
    City varchar(40) NOT NULL,
    County varchar(40) NOT NULL,
    EirCode varchar(8) NOT NULL,
    Email varchar(40),
    PhoneNumber varchar(20),
    MobileNumber varchar(20) NOT NULL
);

CREATE TABLE Customer (
    CustomerID varchar(9) PRIMARY KEY,
    DetailID integer FOREIGN KEY REFERENCES ContactDetail(DetailID),
    LastActivity date NOT NULL,
    CustumerStatus varchar(9) NOT NULL
);

CREATE TABLE SalesPerson (
    SalesPersonID varchar(9) PRIMARY KEY,
    DetailID integer FOREIGN KEY REFERENCES ContactDetail(DetailID)
);

CREATE TABLE Mechanic (
    MechanicID varchar(9) PRIMARY KEY,
    DetailID integer FOREIGN KEY REFERENCES ContactDetail(DetailID)
);

CREATE TABLE Car (
    CarSerialNumber varchar(12) PRIMARY KEY,
    CarIsForSale varchar(1) NOT NULL,
    CarCondition varchar(1) NOT NULL,
    CarMiliage integer,
    CarMake varchar(40),
    CarModel varchar (40),
    CarYear date,
    CarColor varchar (20),
    CarTransmission varchar (10),
    CarEngineSize varchar (10),
    CarFuelType varchar (10),
    CarDoors integer,
    CarBodyStyle varchar (20),
    CarSalePrice decimal (19,4)
);

CREATE TABLE Invoice (
    InvoiceNumber integer IDENTITY(1,1) PRIMARY KEY,
    SalesPersonID varchar(9) FOREIGN KEY REFERENCES SalesPerson(SalesPersonID),
    CustomerID varchar(9) FOREIGN KEY REFERENCES Customer(CustomerID),
    CarSerialNumber varchar(12) FOREIGN KEY REFERENCES Car(CarSerialNumber),
    InvoiceDate datetime NOT NULL,
);

CREATE TABLE ServiceTicket (
    ServiceNumber varchar(9) PRIMARY KEY,
    MechanicID varchar(9) FOREIGN KEY REFERENCES Mechanic(MechanicID),
    CustomerID varchar(9) FOREIGN KEY REFERENCES Customer(CustomerID),
    CarSerialNumber varchar(12) FOREIGN KEY REFERENCES Car(CarSerialNumber),
    ServiceTicketDate date NOT NULL,
    ServiceDue date NOT NULL,
    ServiceDescription varchar (80) NOT NULL,
    ServicePrice decimal(19,4) NOT NULL,
);

【问题讨论】:

为使用的数据库添加标签。数据库是否具有关系完整性和级联删除功能集(例如可以在 Access 中完成)。为每个表运行 DELETE 操作 SQL。为什么还要删除数据? 您不能使用单个查询从多个表中删除行。我建议在 Customer 表上使用 DELETE 触发器,从它们各自的表中删除其他条目。请参阅 this answer 了解其工作原理。 好吧,您可以更改设计并在contactdetail 中引用customer,而不是反过来,并将引用customer 的外键的操作设置为ON DELETE CASCADE。然后,当客户被删除时,这将自动删除所有相关数据。 @Jesse 这是给 Oracle 的,请参阅下面我的回答 【参考方案1】:

正如@stickybit 所说,如果设置正确,您可以使用级联删除。下面是一个测试用例。

create table parent (
  id NUMBER(10),
  value      varchar2(30),
constraint parent_pk primary key (id)
);

CREATE TABLE child
( id NUMBER(10) not null,
value NUMBER(10) not null,
constraint child_pk primary key (id,value),
CONSTRAINT parent_child_fk
FOREIGN KEY (id)
REFERENCES parent(id)
ON DELETE CASCADE
);

CREATE TABLE grandchild
( id NUMBER(10) not null,
value NUMBER(10) not null,
constraint grandchild_pk primary key (id,value),
CONSTRAINT child_grandchild_fk
FOREIGN KEY (id,value)
REFERENCES child(id,value)
ON DELETE CASCADE
);


insert into parent values (1,'a');
insert into parent values (2,'b');
insert into parent values (3,'c');

insert into child  values (1,1);
insert into child  values (1,2);
insert into child  values (1,3);
insert into child  values (2,1);
insert into child  values (2,2);
insert into child  values (2,3);
insert into child  values (3,1);
insert into child  values (3,2);
insert into child  values (3,3);

insert into grandchild  values (1,1);
insert into grandchild  values (1,2);
insert into grandchild  values (1,3);
insert into grandchild  values (2,1);
insert into grandchild  values (2,2);
insert into grandchild  values (2,3);
insert into grandchild  values (3,1);
insert into grandchild  values (3,2);
insert into grandchild  values (3,3);

SELECT  (
        SELECT COUNT(*)
        FROM   parent 
        ) AS parent_cnt,
       (
        SELECT COUNT(*)
        FROM   child 
        ) AS child_cnt,
        (
        SELECT COUNT(*)
        FROM   grandchild
        ) AS grandchild_cnt
FROM    dual

PARENT_CNT  CHILD_CNT   GRANDCHILD_CNT
3   9   9


DELETE from parent where value = 'a';

SELECT  (
        SELECT COUNT(*)
        FROM   parent 
        ) AS parent_cnt,
       (
        SELECT COUNT(*)
        FROM   child 
        ) AS child_cnt,
        (
        SELECT COUNT(*)
        FROM   grandchild
        ) AS grandchild_cnt
FROM    dual

PARENT_CNT    CHILD_CNT    GRANDCHILD_CNT
2    6    6

Here is a query you can use to show the relationships.


with f as (
        select constraint_name, table_name, r_constraint_name
        from   user_constraints
        where  constraint_type = 'R'
     ),
     p as (
        select constraint_name, table_name
        from   user_constraints
        where  constraint_type = 'P'
     ),
     j (child_table, f_key, parent_table, p_key) as (
        select f.table_name, f.constraint_name, p.table_name, f.r_constraint_name
        from   p join f on p.constraint_name = f.r_constraint_name
        union all
        select 'PARENT', (select constraint_name from p                                where table_name = 'PARENT'), null, null from dual
     )
select level as lvl, j.*
from j
start with parent_table is null
connect by nocycle parent_table = prior child_table
order by lvl, parent_table, child_table;

所以现在当我们从父表中删除时,Oracle 将检查是否有 FK 引用父表的表,并会找到表子表。然后它将一一检查要删除的表父行是否在表子中具有子行。如果不是,它将删除该表父行。如果有子级 if 将检查 FK 操作,并且由于该 FK 具有 ON DELETE CASCADE,Oracle 将尝试删除该表的子行。那时它将(与表父表相同)检查是否有 FK 引用表子表的表,并将找到表孙子表。同样,如果要删除的表子行在表孙子中是否有子项,它将一一检查。如果不是,它将删除该表子行。如果有子级 if 将检查 FK 操作,并且由于该 FK 具有 ON DELETE CASCADE,Oracle 将尝试删除该表的孙行。由于表grandchild 没有子表,Oracle 将删除表grandchild、child 和parent 中的相应行。

【讨论】:

以上是关于如何从表和所有引用中删除数据? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

从表中删除孤立记录[关闭]

如何使用 FMDB 从表中删除所有数据

如何在关闭浏览器时从数据库中删除数据

如何在Oracle中添加一个策略,用户可以从表中选择所有数据,并且只能插入、更新、删除有条件的数据

如何从表中删除然后删除引用的已删除行? (postgresql)

如何从 Laravel 项目中删除所有迁移但保留表和字段