参数说明
| 参数 | 说明 |
|---|---|
| LOW_PRIORITY | 如果指定了 LOW_PRIORITY,删除操作将延迟到没有进程从表中读取数据时执行 |
| IGNORE | 如果指定了 IGNORE,删除过程中遇到的所有错误将被忽略 |
| table | 要从中删除记录的表 |
| WHERE conditions | 必须满足的条件,满足条件的记录才会被删除。如果未提供条件,则表中的所有记录都将被删除 |
| ORDER BY expression | 如果指定了 ORDER BY,将按给定的顺序删除记录 |
| LIMIT | 控制要从表中删除的最大记录数。将删除指定的行数 |
第 11.1 节:多表删除
MySQL 的 DELETE 语句可以使用 JOIN 结构,也允许指定要从哪些表中删除。这对于避免嵌套查询很有用。给定以下模式:
CREATE TABLE people (
id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
gender CHAR(1) NOT NULL
);
INSERT INTO people (id, name, gender) VALUES
(1, 'Kathy', 'f'),
(2, 'John', 'm'),
(3, 'Paul', 'm'),
(4, 'Kim', 'f');
CREATE TABLE pets (
id INT AUTO_INCREMENT PRIMARY KEY,
ownerId INT NOT NULL,
name VARCHAR(100) NOT NULL,
color VARCHAR(100) NOT NULL
);
INSERT INTO pets (ownerId, name, color) VALUES
(1, 'Rover', 'beige'),
(2, 'Bubbles', 'purple'),
(3, 'Spot', 'black and white'),
(1, 'Rover2', 'white');
people 表内容:
| id | name | gender |
|---|---|---|
| 1 | Kathy | f |
| 2 | John | m |
| 3 | Paul | m |
| 4 | Kim | f |
pets 表内容:
| id | ownerId | name | color |
|---|---|---|---|
| 1 | 1 | Rover | beige |
| 2 | 2 | Bubbles | purple |
| 3 | 3 | Spot | black and white |
| 4 | 1 | Rover2 | white |
如果我们想删除 Paul 的宠物,下面的语句:
DELETE p2
FROM pets p2
WHERE p2.ownerId IN (SELECT p1.id FROM people p1 WHERE p1.name = 'Paul');
可以重写为:
DELETE p2 -- 只从 pets 表中删除行
FROM people p1
JOIN pets p2 ON p2.ownerId = p1.id
WHERE p1.name = 'Paul';
结果:1 行受影响,Spot 从 pets 中删除。
p1 和 p2 是表名的别名,对于长表名和提高可读性特别有用。
要同时删除人和宠物:
DELETE p1, p2 -- 从两个表中删除行
FROM people p1
JOIN pets p2 ON p2.ownerId = p1.id
WHERE p1.name = 'Paul';
结果:2 行受影响,Spot 从 pets 删除,Paul 从 people 删除。
外键约束
当 DELETE 语句涉及具有外键约束的表时,优化器处理表的顺序可能与关系不符。例如,向 pets 表添加外键:
ALTER TABLE pets ADD CONSTRAINT fk_pets_2_people
FOREIGN KEY (ownerId) REFERENCES people(id) ON DELETE CASCADE;
此时,引擎可能会尝试先从 people 表中删除记录,然后才处理 pets 表,从而导致以下错误:
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails
此问题的解决方案是从 people 表中删除行,并依赖 InnoDB 的 ON DELETE CASCADE 功能来传播删除:
DELETE FROM people WHERE name = 'Paul';
结果:2 行受影响,Paul 从 people 删除,Spot 通过级联从 pets 删除。
另一种解决方案是临时禁用外键检查:
SET foreign_key_checks = 0;
DELETE p1, p2
FROM people p1
JOIN pets p2 ON p2.ownerId = p1.id
WHERE p1.name = 'Paul';
SET foreign_key_checks = 1;
第 11.2 节:DELETE 与 TRUNCATE
TRUNCATE TABLE tableName;
这将删除所有数据并重置 AUTO_INCREMENT 索引。在大型数据集上,它比 DELETE FROM tableName 快得多。在开发/测试期间非常有用。
当你 truncate 一个表时,SQL 服务器实际上并没有删除数据,而是删除表并重新创建它,从而释放页(deallocating the pages),因此在页被覆盖之前有机会恢复被 truncate 的数据。(对于 innodb_file_per_table=OFF 的情况,空间不能立即被回收。)
第 11.3 节:多表 DELETE(再次说明)
MySQL 允许指定匹配的行要从哪个表中删除。
- 只删除员工:
DELETE e
FROM Employees e
JOIN Department d ON e.department_id = d.department_id
WHERE d.name = 'Sales';
- 删除员工和部门:
DELETE e, d
FROM Employees e
JOIN Department d ON e.department_id = d.department_id
WHERE d.name = 'Sales';
- 从所有表中删除(此例中同上一行):
DELETE FROM Employees
USING Employees e
JOIN Department d ON e.department_id = d.department_id
WHERE d.name = 'Sales';
(注意:实际语法可能略有不同,此处保留原文意)
第 11.4 节:基本删除
DELETE FROM myTable WHERE someColumn = 'something';
WHERE 子句是可选的,但如果没有它,所有行将被删除。
第 11.5 节:带 WHERE 子句的删除
DELETE FROM table_name WHERE field_one = 'value_one';
这将删除表中所有 field_one 列的值等于 'value_one' 的行。
WHERE 子句的工作方式与 SELECT 相同,因此可以使用 >、<、<> 或 LIKE 等操作符。
注意: 在删除查询中使用条件子句(WHERE、LIKE)是必要的。如果不使用任何条件子句,表中的所有数据都将被删除。
第 11.6 节:删除表中的所有行
DELETE FROM table_name;
这将删除表中的所有内容,所有行。这是语法的最基本示例。同时也表明,DELETE 语句应该非常小心地使用,因为如果省略 WHERE 子句,可能会清空整个表。
第 11.7 节:限制删除的行数
DELETE FROM table_name WHERE field_one = 'value_one' LIMIT 1;
这类似于“带 WHERE 子句的删除”示例,但它会在删除达到限制数量后停止删除。
如果像这样限制删除的行数,请注意,它将删除符合条件的第一行。由于结果可能在没有显式排序的情况下以不确定的顺序返回,删除的可能不是你所期望的那一行。