SQL COMMAND · 查询与数据操作
DELETE
删除表中的行
delete rows of a table
DELETE查询与数据操作引入 6.4(基线)现存至 20 devel11 次语法变更
- 动词
DELETE- 对象
—- 分组
- 查询与数据操作
- 引入版本
- 6.4(基线)
- 状态
- 现存
- 语法变更次数
- 11
- 手册小节数
- 7
版本轨迹
相对 PostgreSQL 17:语法概要新增 1 行,移除 0 行。
语法铁道图 PostgreSQL 18
沿轨道从左向右阅读,分岔表示选择,绕行表示可选,回环表示重复。方框为参数,点击带下划线的参数可展开子规则。
锁模式 PostgreSQL 18
具体锁模式取决于操作变体、目标对象和执行阶段;同一命令可同时取得表锁与行锁。查看完整冲突矩阵
ROW EXCLUSIVE· 表级锁DELETE:目标表取得此模式;删除的已有行另有 FOR UPDATE 行锁。FOR UPDATE· 行级锁DELETE:在被删除的已有行上取得此模式;目标表同时取得 ROW EXCLUSIVE。
语法概要
相对 PostgreSQL 17 新增 1 行,移除 0 行;新增行以绿色标记。
[ WITH [ RECURSIVE ] with_query [, ...] ] DELETE FROM [ ONLY ] table_name [ * ] [ [ AS ] alias ] [ USING from_item [, ...] ] [ WHERE condition | WHERE CURRENT OF cursor_name ] [ RETURNING [ WITH ( { OLD | NEW } AS output_alias [, ...] ) ] { * | output_expression [ [ AS ] output_name ] } [, ...] ]
描述
DELETE 从指定表中删除满足
WHERE 子句的行。如果省略 WHERE
子句,效果就是删除表中的所有行。结果是一个合法但为空的表。
提示
TRUNCATE 提供了一种更快的机制来移除表中的所有行。
有两种方法可以利用数据库中其他表所包含的信息来删除一个表中的行:使用子选择,或者在 USING 子句中指定附加表。哪种技术更合适取决于具体情况。
可选的 RETURNING 子句使 DELETE
基于每个实际被删除的行计算并返回一个或多个值。可以计算使用该表列和/或 USING 中提到的其他表列的任意表达式。RETURNING 列表的语法与 SELECT
的输出列表相同。
要从一个表中删除行,必须具有该表上的 DELETE 权限,以及 USING 子句中出现的任何表或者其值会在
condition 中读取的任何表上的 SELECT 权限。
参数
with_queryWITH子句允许你指定一个或多个子查询,这些子查询可在DELETE查询中按名称引用。详见第 7.8 节和 SELECT。table_name要从中删除行的表名(可以是模式限定的)。如果在表名前指定了
ONLY,只会从所提及表中删除匹配行。如果未指定ONLY,还会删除继承自该表的任何表中的匹配行。可选地,可以在表名后指定*,以显式指示包含后代表。alias目标表的替代名称。提供别名时,它会完全隐藏该表的实际名称。例如,给定
DELETE FROM foo AS f,DELETE语句的其余部分必须将该表称为f,而不是foo。from_item一个表表达式,允许其他表的列出现在
WHERE条件中。这里使用的语法与SELECT语句的FROM子句相同;例如,可以为表名指定别名。除非你打算进行自连接(这种情况下它必须在from_item中带有别名出现),否则不要把目标表重复写成from_item。condition一个返回
boolean类型值的表达式。只有使这个表达式返回true的行才会被删除。cursor_name要在
WHERE CURRENT OF条件中使用的游标名。要被删除的行是最近一次从该游标中取出的那一行。该游标必须是针对DELETE目标表的非分组查询。注意,WHERE CURRENT OF不能与布尔条件同时指定。有关将游标用于WHERE CURRENT OF的更多信息,请见 DECLARE。output_alias在
RETURNING列表中为OLD或NEW行指定的可选替代名称。默认情况下,可通过
OLD.或column_nameOLD.*返回目标表旧值,通过NEW.或column_nameNEW.*返回新值。提供别名后,这些名称会被隐藏,必须使用别名来引用旧行或新行。例如RETURNING WITH (OLD AS o, NEW AS n) o.*, n.*。output_expression在每一行被删除后,由
DELETE命令计算并返回的表达式。该表达式可以使用由table_name命名的表或USING中列出的表的任何列名。写成*可返回所有列。列名或
*可以用OLD或NEW进行限定,也可以用OLD或NEW对应的output_alias进行限定,以返回旧值或新值。未限定的列名或*,以及用目标表名称或别名限定的列名或*,都会返回旧值。对于简单的
DELETE,所有新值都将为NULL。但是,如果某个ON DELETE规则导致转而执行INSERT或UPDATE,那么新值可能为非NULL。output_name用于返回列的名称。
输出
在成功完成时,一个 DELETE 命令会返回以下形式的命令标签:
DELETE count
count 是被删除的行数。注意,当删除被 BEFORE DELETE 触发器抑制时,这个数量可能小于匹配 condition
的行数。如果 count 为 0,则该查询没有删除任何行(这不被视为错误)。
如果 DELETE 命令包含 RETURNING
子句,其结果将类似于一个 SELECT 语句,其中包含
RETURNING 列表中定义的列和值,并在该命令删除的行上进行计算。
注解
PostgreSQL 允许通过在
USING 子句中指定其他表,在
WHERE 条件中引用这些表的列。例如,要删除由给定制片人制作的所有电影,可以这样做:
DELETE FROM films USING producers WHERE producer_id = producers.id AND producers.name = 'foo';
本质上,这里发生的是在 films 和
producers 之间进行连接,并将所有成功连接到的 films 行标记为删除。这种语法不是标准的。更标准的写法是:
DELETE FROM films WHERE producer_id IN (SELECT id FROM producers WHERE name = 'foo');
在某些情况下,连接形式比子选择形式更容易书写或者执行更快。
示例
删除所有电影,但音乐剧除外:
DELETE FROM films WHERE kind <> 'Musical';
清空表 films:
DELETE FROM films;
删除已完成的任务,并返回被删除行的完整详情:
DELETE FROM tasks WHERE status = 'DONE' RETURNING *;
删除游标 c_tasks 当前所定位的
tasks 行:
DELETE FROM tasks WHERE CURRENT OF c_tasks;
虽然 DELETE 没有 LIMIT 子句,但可以采用 UPDATE 文档中介绍的相同方法来获得类似效果:
WITH delete_batch AS (
SELECT l.ctid FROM user_logs AS l
WHERE l.status = 'archived'
ORDER BY l.creation_date
FOR UPDATE
LIMIT 10000
)
DELETE FROM user_logs AS dl
USING delete_batch AS del
WHERE dl.ctid = del.ctid;
这里使用 ctid 之所以安全,仅仅是因为该查询会被重复执行,从而避免了 ctid 发生变化的问题。
兼容性
这个命令符合 SQL 标准,不过
USING 和 RETURNING 子句是
PostgreSQL 扩展,在
DELETE 中使用 WITH 也是扩展。
另见
语法演化
相邻大版本之间的差异,新的在前。版本号链接到对应快照。
PostgreSQL 18← 17语法变化
+ [ RETURNING [ WITH ( { OLD | NEW } AS output_alias [, ...] ) ]正文更新PostgreSQL 17← 16正文更新
正文更新PostgreSQL 13← 12正文更新
正文更新PostgreSQL 12← 11语法变化
+ [ RETURNING { * | output_expression [ [ AS ] output_name ] } [, ...] ]PostgreSQL 10← 9.6正文更新
正文更新PostgreSQL 9.5← 9.4语法变化
+ [ USING from_item [, ...] ]− [ USING using_list ]正文更新PostgreSQL 9.2← 9.1语法变化
+ DELETE FROM [ ONLY ] table_name [ * ] [ [ AS ] alias ]− DELETE FROM [ ONLY ] table [ * ] [ [ AS ] alias ]正文更新PostgreSQL 9.1← 9.0语法变化
+ [ WITH [ RECURSIVE ] with_query [, ...] ]正文更新PostgreSQL 9.0← 8.4语法变化
+ [ USING using_list ]− [ USING usinglist ]正文更新PostgreSQL 8.4← 8.3语法变化
+ [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]正文更新PostgreSQL 8.3← 8.2语法变化
+ DELETE FROM [ ONLY ] table [ * ] [ [ AS ] alias ]+ [ WHERE condition | WHERE CURRENT OF cursor_name ]正文更新PostgreSQL 8.2← 8.1语法变化
+ DELETE FROM [ ONLY ] table [ [ AS ] alias ]+ [ RETURNING * | output_expression [ AS output_name ] [, ...] ]正文更新PostgreSQL 8.1← 8.0语法变化
+ [ USING usinglist ]+ [ WHERE condition ]正文更新PostgreSQL 8.0← 7.4正文更新
正文更新PostgreSQL 7.4← 7.3正文更新
正文更新PostgreSQL 7.2← 7.1正文更新
正文更新PostgreSQL 7.1← 7.0语法变化
sql-delete.htm → sql-delete.html
+ DELETE FROM [ ONLY ] table [ WHERE condition ]正文更新PostgreSQL 7.0← 6.5正文更新
正文更新PostgreSQL 6.5← 6.4正文更新
正文更新
同组命令
| 命令 | 动词 | 对象 | 版本变动 | 最近变更 |
|---|---|---|---|---|
COPY | COPY | — | 1917 次 | |
| 在文件和表之间复制数据 | 现存 | |||
DELETE | DELETE | — | 1811 次 | |
| 删除表中的行 | 现存 | |||
EXPLAIN | EXPLAIN | — | 1910 次 | |
| 显示一个语句的执行计划 | 现存 | |||
INSERT | INSERT | — | 1912 次 | |
| 在表中插入新行 | 现存 | |||
LOCK | LOCK | — | 9.07 次 | |
| 锁定表 | 现存 | |||
MERGE | MERGE | — | 182 次 | |
| 有条件地插入、更新或删除表中的行 | 现存 | |||
SELECT | SELECT | — | 1722 次 | |
| 从表或视图中检索行 | 现存 | |||
UPDATE | UPDATE | — | 1813 次 | |
| 更新表中的行 | 现存 | |||
VALUES | VALUES | — | 8.41 次 | |
| 计算一组行 | 现存 | |||
SELECT INTO | SELECT | INTO | 1913 次 | |
| 根据查询结果定义一个新表 | 现存 | |||