DELETE — 删除表中的行
[ WITH [ RECURSIVE ]with_query
[, ...] ] DELETE FROM [ ONLY ]table_name
[ * ] [ [ AS ]alias
] [ USINGfrom_item
[, ...] ] [ WHEREcondition
| WHERE CURRENT OFcursor_name
] [ RETURNING [ WITH ( { OLD | NEW } ASoutput_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 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_name
OLD.*
返回目标表中的旧值,通过编写 NEW.
或 column_name
NEW.*
返回新值。提供别名时,将隐藏这些名称,并且必须使用别名引用旧行或新行。例如 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
子句,则结果将类似于包含RETURNING
列表中定义的列和值的SELECT
语句,该语句针对命令删除的行(或多行)进行计算。
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;
此命令符合SQL标准,不同之处在于USING
和RETURNING
子句是PostgreSQL扩展,WITH
可与DELETE
一起使用也是如此。
如果您在文档中看到任何不正确、不符合您对特定功能的使用经验或需要进一步澄清的内容,请使用此表格报告文档问题。