关系型数据库(RDBMS)级联删除

 

数据库操作中,级联删除(Cascade)是一种处理数据表之间关联数据的方式。用于在删除主表(父表)中的一条记录时,自动删除与该条数据相关联的子表内的数据。

 

1. 适用数据库 

级联删除(Cascade Delete)适用于多个主流的关系数据库管理系统(RDBMS):
 1) PostgreSQL:
  支持级联删除,使用 ON DELETE CASCADE 在定义外键时指定。
  当父表中删除记录时,所有在子表内与之关联的记录也会被自动删除。

 2) MySQL
  支持级联删除,使用 ON DELETE CASCADE 在外键定义时被指定。
  注意:MySQL中的 InnoDB 引擎支持级联删除,但MyISAM 引擎并不支持外键约束,故不支持级联删除。

 3) Orcla
  支持级联删除,使用 ON DELETE CASCADE。
  当删除父表中的记录时,Orcla 会 自动删除子表的对应的记录。

 4) SQL Server
  支持级联删除,使用 ON DELETE CASCADE。
  可以创建或修改外键时指定级联删除行为。

 5) SQLite
  支持级联删除,但需在启用外键约束的情况下使用。
  使用 PRAGMA foreign_keys = on; 启用外键约束后,可以使用 ON DELETE CASCADE。

 6) MariaDB
  作为MySQL的一个分支,MariaDB也支持级联删除,方式与 MySQL 类型。

 7) DB2(IBM)
  支持级联删除,使用 ON DELETE CASCADE。
  在DB2中,可以在外键约束中指定级联删除规则。

 

2. 使用场景

使用场景:
 级联删除在数据库设计,有明确的父子表关系场景中;如订单及其项、用户及其日志记录等。在这些场景时,级联删除可以确保在删除父表中的记录时,不会遗留无用的子表记录,从而保持数据的一致性和完整性。

 

3. 实现方式

级联删除可以通过两种方式实现:
 1) 使用事务手动实现级联删除
  在事务中执行多个 delete 语句,根据外键关系依次删除相关的记录。
  这种方法需要明确控制删除顺序,确保在删除父记录前先删除相关的子记录,以避免外键约束的冲突。

 

创建表 和 外键关系:(orders-父表 和 order_items-子表;从表中的每条数据与父表的单条数据关联)。

-- 创建父表 orders
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,  -- 自增主键
    order_date DATE NOT NULL,
    customer_name VARCHAR(255) NOT NULL
);

-- 创建子表 order_items
CREATE TABLE order_items (
    id SERIAL PRIMARY KEY,  -- 自增主键
    order_id INT NOT NULL,  -- 外键,引用 orders 表
    product_name VARCHAR(255) NOT NULL,
    quantity INT NOT NULL,
    FOREIGN KEY (order_id) REFERENCES orders(id)  -- 定义外键约束
);

 

删除 orders 表内的数据与子表所有与之关联的 order_item的数据。

 顺序:必须先删除子表的记录,然后再删除父标的记录。

 事务:确保操作是原子性的,要么全部成功,要么全部失败,以确保数据的一致性。

SQL是这样的:

BEGIN;  -- 开始事务

-- 删除子表 order_items 中与 order_id = 1 关联的所有记录
DELETE FROM order_items WHERE order_id = 1;

-- 删除父表 orders 中 id = 1 的记录
DELETE FROM orders WHERE id = 1;

COMMIT;  -- 提交事务

 

使用 Mybtis 时 xml 文件执行:

<delete id="deleteOrderWithItems">
    <!-- 删除子表 order_items 中与 order_id 关联的所有记录 -->
    DELETE FROM order_items WHERE order_id = #{id};

    <!-- 删除父表 orders 中 id 的记录 -->
    DELETE FROM orders WHERE id = #{id};
</delete>

 

 2) 使用数据库的 CASCADE 规则
  在定义外键约束时,可以指定 on delete cascade,当父记录被删除时,数据库会自动删除所有关联的子记录。
  这种方法是数据库层面的一种自动化处理方式,无需手动编写多个删除语句。

 

创建表 和 外键关系:(orders-父表 和 order_items-子表;从表中的每条数据与父表的单条数据关联)。

-- 创建父表 orders
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,  -- 自增主键
    order_date DATE NOT NULL,
    customer_name VARCHAR(255) NOT NULL
);

-- 创建子表 order_items,并定义外键,指定 on delete cascade
CREATE TABLE order_items (
    id SERIAL PRIMARY KEY,  -- 自增主键
    order_id INT NOT NULL,  -- 外键,引用 orders 表
    product_name VARCHAR(255) NOT NULL,
    quantity INT NOT NULL,
    FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE  -- 定义外键约束,启用级联删除
);

order_items-子表 外键 order_id 引用 orders-父表 id。

 

SQL是:

-- 删除 orders 表中 id = 1 的记录
DELETE FROM orders WHERE id = 1;

 

mxl文件语法:

<!-- 删除 orders 表中 id = ... 的记录 -->
<delete id="deleteOrderById">
    delete from orders where id = #{id};
</delete>

定义了外键时使用了 'ON DELETE CASCADE',数据库会自动删除 '从表' 对应的 'order_id' 的数据。 

 

4. ON DELETE外键

外键(Froreign Key)是一种数据库约束,用于在两个表之间建立关系。外键通常用于与另一个表的主键(Primark Key),并确保引用完整性,保证外键列中的值必须在被引用的表中存在。

外键约束多种类型的规则和选项,可以控制在发生数据变更时的行为。

CASCADE

当主表的一条记录被删除时,所有引用该记录的子表中的记录也会被自动删除。

场景:当删除某条记录时,必须同时删除与该记录关联的所有的子记录(如订单与订单项)。

SET NULL

当主表的一条记录被删除时,子表中引用该记录的外键字段会被设置为 NULL。

场景:当删除主记录时,子记录可以保留,但需要设置外键为 NULL(如文章和作者,删除作者但文章继续显示但不显示作者)。

RESTRICT

机制删除主表中的记录,如果该记录被子表引用,则无法删除。

场景:严格禁止删除有依赖关系的主记录,确保所有关联的子记录先被处理。

NO ACTION

类似于 'RESTRICT',但在某些数据库系统中,它的行为取决于其他触发器或约束。

场景:用于不想执行任何级联操作的场合。

SET DEFAULT

当主表的一条记录被删除时,子表引用该记录的外键字段会被设置为预定义的默认值。

场景:当删除主记录时,子记录保留,但外键字段设置为默认值(如产品分类,删除分类时,产品的分类字段这是为默认分类)。

 

5. 注意事项

 性能影响:在大量数据删除时,级联删除可能会影响性能,尤其在子表记录很多的情况下。
 数据丢失风险:级联删除会自动删除与其相关的子表记录,因此慎重使用,防止意外丢失重要的数据。
 外键约束:需要注意数据库引擎是否支持外键约束(如MySQL的MyISAM引擎不支持)。

 

 


 

posted @ 2024-09-03 12:17  学Java的`Bei  阅读(169)  评论(0编辑  收藏  举报