2024 年 9 月 26 日: PostgreSQL 17 发布!
支持的版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不支持的版本:11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

DELETE

DELETE — 删除表中的行

概要

[ WITH [ RECURSIVE ] with_query [, ...] ]
DELETE FROM [ ONLY ] table_name [ * ] [ [ AS ] alias ]
    [ USING from_item [, ...] ]
    [ WHERE condition | WHERE CURRENT OF cursor_name ]
    [ RETURNING { * | output_expression [ [ AS ] output_name ] } [, ...] ]

描述

DELETE 删除满足指定表中 WHERE 子句的行的。如果 WHERE 子句不存在,则删除表中的所有行。结果是一个有效的空表。

提示

TRUNCATE 提供了从表中删除所有行的更快机制。

有两种方法可以使用数据库中其他表中包含的信息来删除表中的行:使用子查询或在 USING 子句中指定其他表。哪种技术更合适取决于具体情况。

可选的 RETURNING 子句会导致 DELETE 计算并返回基于实际删除的每一行的值。可以使用表的列和/或在 USING 中提到的其他表的列计算任何表达式。 RETURNING 列表的语法与 SELECT 的输出列表的语法相同。

您必须对表具有 DELETE 权限才能从表中删除,并且必须对 USING 子句中或其值在 condition 中读取的任何表具有 SELECT 权限。

参数

with_query

WITH 子句允许您指定一个或多个子查询,这些子查询可以在 DELETE 查询中按名称引用。有关详细信息,请参阅 第 7.8 节SELECT

table_name

要从其删除行的表名称(可选的模式限定)。如果在表名称之前指定 ONLY,则仅从指定的表中删除匹配的行。如果没有指定 ONLY,则也会从继承指定表的任何表中删除匹配的行。可选地,可以在表名称后指定 * 来明确指示包含后代表。

alias

目标表的替代名称。当提供别名时,它会完全隐藏表的实际名称。例如,给定 DELETE FROM foo AS fDELETE 语句的其余部分必须将此表引用为 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_expression

在每行删除后由 DELETE 命令计算并返回的表达式。该表达式可以使用由 table_name 或在 USING 中列出的表命名的表的任何列名称。编写 * 以返回所有列。

output_name

用于返回列的名称。

输出

成功完成时, DELETE 命令返回以下形式的命令标签

DELETE count

count 是删除的行数。请注意,当 BEFORE DELETE 触发器抑制删除时,该数字可能小于与 condition 匹配的行数。如果 count 为 0,则查询未删除任何行(这不被视为错误)。

如果 DELETE 命令包含 RETURNING 子句,则结果将类似于包含 RETURNING 列表中定义的列和值的 SELECT 语句,在命令删除的行上计算。

注意

PostgreSQL 允许您通过在 USING 子句中指定其他表来在 WHERE 条件中引用其他表的列。例如,要删除由给定制片人制作的所有电影,可以执行以下操作

DELETE FROM films USING producers
  WHERE producer_id = producers.id AND producers.name = 'foo';

这里实际上是在 filmsproducers 之间进行连接,所有成功连接的 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;

兼容性

此命令符合SQL标准,除了 USINGRETURNING 子句是 PostgreSQL 扩展,以及将 WITHDELETE 一起使用也是 PostgreSQL 扩展。

另请参阅

TRUNCATE

提交更正

如果您在文档中看到任何不正确的内容,与您对特定功能的体验不符,或者需要进一步澄清,请使用 此表格 报告文档问题。