MySQL 零基础教程

MySQL DELETE 语句

MySQL 中的 DELETE 语句用于从表中移除已存在的行。与用于修改数据的 UPDATE 不同,DELETE 会永久擦除完整的记录。如果你需要移除特定的数据行,DELETE 语句就是你必备的工具。

1. 基础 DELETE 语句

删除记录最直接的方法是指定你想要从中移除数据的表。

DELETE FROM your_table_name;
危险警告: 如果执行 DELETE FROM your_table_name; 时不带 WHERE 子句,将会删除 your_table_name 表中的所有行。这是一个极具破坏性的操作,必须格外谨慎使用。在运行 DELETE 语句之前,请务必反复检查你的 WHERE 子句。

为了方便演示,我们假设有一个名为 products(产品)的表,它目前的数据如下:

product_id (产品ID)name (名称)category (类别)price (价格)stock_quantity (库存量)
1LaptopElectronics120050
2MouseElectronics25200
3KeyboardElectronics75150
4Desk ChairFurniture30030
5Table LampHome Decor4080
6MonitorElectronics40070

2. 使用 WHERE 子句删除特定行

要仅移除特定的记录,你必须包含一个 WHERE 子句。该子句会过滤数据行,确保只删除那些符合指定条件的记录。这与你在 SELECTUPDATE 语句中使用 WHERE 的方式非常相似。

假设你想移除 product_id 为 5 的产品(Table Lamp/台灯)。

DELETE FROM products
WHERE product_id = 5;

执行此操作后,products 表将变成这样(第 5 行被永久移除):

product_idnamecategorypricestock_quantity
1LaptopElectronics120050
2MouseElectronics25200
3KeyboardElectronics75150
4Desk ChairFurniture30030
6MonitorElectronics40070

你可以在 WHERE 子句中使用任何有效的条件,使用 ANDORNOT 组合多个条件,并使用诸如 ><>=<==!=LIKEINBETWEENIS NULL 等运算符。

2.1 基于类别删除多行

假设你决定移除 'Home Decor'(家居装饰)类别下的所有产品。

DELETE FROM products
WHERE category = 'Home Decor';

如果表中目前包含 'Home Decor' 物品,这条语句会将它们全部移除。

2.2 删除低库存行

你可能想要移除那些几乎缺货且不再进货的产品,例如 stock_quantity(库存量)小于 10 的产品。

DELETE FROM products
WHERE stock_quantity < 10;

2.3 基于价格和类别组合删除

考虑删除所有价格低于 50 美元的 'Electronics'(电子产品)。

DELETE FROM products
WHERE category = 'Electronics' AND price < 50;

这条语句使用 AND 组合了两个条件,确保只有同时满足这两个条件的行才会被删除。在我们最初的表格示例中,这将会删除 'Mouse'(product_id 为 2)。

3. DELETE 语句执行流程

删除记录的过程始终涉及检查条件,以确保定位到正确的数据:

  1. 开始 DELETE 语句
  2. 是否存在 WHERE 子句?
    1. 否: 删除表中的所有行。
    2. 是: 针对每一行评估 WHERE 子句。
  3. 当前行是否匹配 WHERE 条件?
    1. 是: 删除当前行。
    2. 否: 保留当前行。
  4. 继续检查下一行,直到遍历完所有行。
  5. 结束 DELETE 语句

4. WHERE 子句与事务控制的重要性

WHERE 子句对于精确的数据操作至关重要。没有它,DELETE 就是一把极其危险的钝器。在真实的实际应用中,DELETE 操作几乎总是被包裹在事务 (Transaction) 中执行,以提供一个安全网。

事务允许你将多个 SQL 语句组合成一个单一的、不可分割的工作单元。如果事务中的任何语句失败,或者你决定撤销更改,你可以使用 ROLLBACK(回滚)整个事务,撤销所有操作。如果一切按计划进行,你可以 COMMIT(提交)事务,使更改永久生效。

以下是一个包裹在事务中的 DELETE 操作的典型示例:

START TRANSACTION; -- 开启事务

    -- 验证你打算删除的行(可选步骤,但强烈推荐)
    SELECT *
    FROM products
    WHERE category = 'Home Decor';

    -- 执行 DELETE 操作
    DELETE FROM products
    WHERE category = 'Home Decor';

    -- 检查受影响的行数(可选,用于验证确认)
    -- SELECT ROW_COUNT();

    -- 如果你绝对确定无误,提交更改:
    -- COMMIT; 

    -- 如果你发现删错了想要撤销更改,取消下面这行的注释:
    -- ROLLBACK;

通过将你的 DELETE 语句放在 START TRANSACTION; 中并且不立即 COMMIT(提交),你给自己留出了机会去检查 SELECT 的结果、执行 DELETE,然后根据结果是否符合预期来决定是 COMMIT 还是 ROLLBACK。这是执行任何破坏性操作的最佳实践。

5. DELETE 与外键约束 (Foreign Key Constraints)

当从表中删除记录时,你需要注意外键约束。如果你试图删除的行在另一个表中被外键引用,MySQL 的行为取决于为该外键定义的 ON DELETE 动作规则:

  • RESTRICT(默认): 如果存在匹配的子行,则阻止删除父行。你将收到一个报错。
  • NO ACTION: 类似于 RESTRICT。如果存在子行,则阻止删除。
  • CASCADE(级联): 删除父行的同时,自动删除所有引用它的子行。这可能会产生广泛的连锁反应,因此请极为谨慎地使用。
  • SET NULL: 删除父行,并将子行中的外键列设置为 NULL。这仅在子表中的外键列允许 NULL 值时才有效。

例如,如果你有一个 orders(订单)表引用了 products(产品)表(即 orders.product_id 是一个引用 products.product_id 的外键),并且如果你尝试删除一个已有订单的产品,且外键设置为 ON DELETE RESTRICT,那么 DELETE 语句将会失败。

-- 假设订单表存在,且其 product_id 引用了产品表的 product_id,规则为 ON DELETE RESTRICT
-- 并且 product_id 为 1 的产品存在关联的订单。

DELETE FROM products
WHERE product_id = 1;

-- 这通常会导致类似如下的错误:
-- ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`your_database`.`orders`, CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`product_id`) REFERENCES `products` (`product_id`))

理解这些 ON DELETE 动作规则对于维护数据完整性,以及预测 DELETE 操作对跨关联表的深远影响至关重要。