2025年9月25日: PostgreSQL 18 发布!
支持的版本:当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本:devel
不支持的版本:12 / 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 [ 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_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_alias

RETURNING 列表中的 OLDNEW 行的可选替代名称。

默认情况下,可以通过编写 OLD.column_nameOLD.* 返回目标表中的旧值,通过编写 NEW.column_nameNEW.* 返回新值。提供别名时,将隐藏这些名称,并且必须使用别名引用旧行或新行。例如 RETURNING WITH (OLD AS o, NEW AS n) o.*, n.*

output_expression

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

列名或*可以使用OLDNEW,或者OLDNEW对应的output_alias来限定,以返回旧值或新值。未限定的列名,或*,或使用目标表名或别名限定的列名或*将返回旧值。

对于简单的DELETE,所有新值都将是NULL。但是,如果ON DELETE规则导致执行INSERTUPDATE,则新值可能不是NULL

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扩展,WITH可与DELETE一起使用也是如此。

另请参阅

TRUNCATE

提交更正

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