保存%ROWTYPE中的行并在之后有效删除它?

时间:2014-10-12 12:09:44

标签: sql postgresql plpgsql

这就是我目前的做法:

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查询的内容并从函数中返回它。以上只是简化了。

2 个答案:

答案 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)(取决于)的部分索引。