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 (库存量) |
|---|---|---|---|---|
| 1 | Laptop | Electronics | 1200 | 50 |
| 2 | Mouse | Electronics | 25 | 200 |
| 3 | Keyboard | Electronics | 75 | 150 |
| 4 | Desk Chair | Furniture | 300 | 30 |
| 5 | Table Lamp | Home Decor | 40 | 80 |
| 6 | Monitor | Electronics | 400 | 70 |
2. 使用 WHERE 子句删除特定行
要仅移除特定的记录,你必须包含一个 WHERE 子句。该子句会过滤数据行,确保只删除那些符合指定条件的记录。这与你在 SELECT 和 UPDATE 语句中使用 WHERE 的方式非常相似。
假设你想移除 product_id 为 5 的产品(Table Lamp/台灯)。
DELETE FROM products
WHERE product_id = 5;执行此操作后,products 表将变成这样(第 5 行被永久移除):
| product_id | name | category | price | stock_quantity |
|---|---|---|---|---|
| 1 | Laptop | Electronics | 1200 | 50 |
| 2 | Mouse | Electronics | 25 | 200 |
| 3 | Keyboard | Electronics | 75 | 150 |
| 4 | Desk Chair | Furniture | 300 | 30 |
| 6 | Monitor | Electronics | 400 | 70 |
你可以在 WHERE 子句中使用任何有效的条件,使用 AND、OR、NOT 组合多个条件,并使用诸如 >、<、>=、<=、=、!=、LIKE、IN、BETWEEN、IS 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 语句执行流程
删除记录的过程始终涉及检查条件,以确保定位到正确的数据:
- 开始 DELETE 语句
- 是否存在 WHERE 子句?
- 否: 删除表中的所有行。
- 是: 针对每一行评估 WHERE 子句。
- 当前行是否匹配 WHERE 条件?
- 是: 删除当前行。
- 否: 保留当前行。
- 继续检查下一行,直到遍历完所有行。
- 结束 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 操作对跨关联表的深远影响至关重要。