这就是我目前的做法:
DECLARE tmp message%ROWTYPE;
BEGIN;
SELECT * INTO tmp FROM [...]
DELETE FROM message m WHERE m.id = tmp.id;
END;
我担心数据库会在这里执行两个查询:一个用于执行SELECT
,另一个用于DELETE
。如果这是真的 - 我能以某种方式提高效率吗?在SELECT
查询中找到所有应删除的行之后。
N.b。我最终存储了来自SELECT
查询的内容并从函数中返回它。以上只是简化了。
答案 0 :(得分:1)
delete from message m
using (
select *
from ...
) s
where m.id = s.id
returning s.*
答案 1 :(得分:1)
对于简单的情况,您甚至不需要子查询。
如果您的秘密第一次查询仅涉及同一个表:
DELETE FROM message m
WHERE m.id = <something>
RETURNING m.*; -- or what you need from the deleted row.
如果您的秘密第一次查询涉及一个或多个附加表:
DELETE FROM message m
USING some_tbl s
WHERE s.some_column = <something>
AND m.id = s.id
RETURNING m.id, s.foo; -- you didn't define ...
一个有根据的猜测,删除每个具有相同timestamp
的最旧行(最小id
):
DELETE FROM message m
USING (
SELECT DISTINCT ON (id)
id, timestamp
FROM message
WHERE queue_id = _queue_id
AND source_client_id = _source_client_id
AND (target_client_id IN (-1, _client_id))
ORDER BY id, timestamp
) sub
WHERE m.id = sub.id
AND m.timestamp = sub.timestamp
RETURNING m.content
INTO rv;
或者,如果(id, timestamp)
为UNIQUE
,则NOT EXISTS
可能更快:
DELETE FROM message m
WHERE queue_id = _queue_id
AND source_client_id = _source_client_id
AND target_client_id IN (-1, _client_id)
AND NOT EXISTS (
SELECT 1
FROM message
WHERE queue_id = _queue_id
AND source_client_id = _source_client_id
AND target_client_id IN (-1, _client_id)
AND id = m.id
AND timestamp < m.timestamp
) sub
WHERE m.id = sub.id
RETURNING m.content
INTO rv;
更多关于DISTINCT ON
并选择&#34;最伟大的&#34;来自每个小组:
如果表现是你的首要目标,请看最后一章......
除此之外:timestamp
是Postgres中的基本类型名称,是标准SQL中的保留字。不要将它用作标识符。
DELETE FROM message m
USING (
SELECT id
FROM message
WHERE queue_id = _queue_id
AND target_client_id IN (client_id, -1)
ORDER BY timestamp
LIMIT 1
) AS tmp
WHERE m.id = tmp.id
RETURNING m.content
INTO rv;
当然, INTO ...
在plpgsql函数中才有意义
(queue_id, timestamp)
上的索引使得这个很快 - 可能甚至是条件为WHERE target_client_id IN (client_id, -1)
(取决于)的部分索引。