在不重做复杂查询的情况下,在其他查询中重用复杂查询结果

时间:2011-11-26 20:57:42

标签: sql postgresql plpgsql common-table-expression

我在PostgreSQL中有一个复杂的查询,我想在UPDATE和DELETE等其他操作中使用它的结果,如:

<COMPLEX QUERY>;
UPDATE WHERE <COMPLEX QUERY RESULT> = ?;
DELETE WHERE <COMPLEX QUERY RESULT> = ?;
UPDATE WHERE <COMPLEX QUERY RESULT> = ?;

我不希望每次操作都要进行一次复杂查询。避免这种情况的一种方法是将结果存储在表中并将其用于WHERE和JOINS,并在完成后删除临时表。

我想知道是否有其他方法没有将结果存储到数据库,但已经在内存中使用结果。

我已经为此使用了循环,但我认为每件事只做一次操作比每行操作要快。

2 个答案:

答案 0 :(得分:2)

如果查询的结果类型与任何现有的查询不匹配,您可以遍历查询结果,如@phatfingers演示(可能使用通用record变量或标量变量而不是rowtype行类型)。对于少量结果行顺序处理是必要的,这是一个好主意。

对于大结果集,您的原始方法的执行速度会快一个数量级。使用一个SQL命令进行批量INSERT / UPDATE / DELETE要便宜得多 而不是逐步写入/删除,一次一行。

临时表是重用此类结果的正确选择。它会在会话结束时自动删除。如果您想立即删除它或在事务结束时删除它,您只需要明确删除。我引用manual here

  

临时表会在会话结束时自动删除,或者   可选地在当前交易结束时。

对于大型临时表,在填充ANALYZE之后运行它是个好主意。

可写CTE

以下是Pavel在评论中添加的演示:

CREATE TEMP TABLE t1(id serial, txt text);
INSERT INTO t1(txt)
VALUES ('foo'), ('bar'), ('baz'), ('bax');

CREATE TEMP TABLE t2(id serial, txt text);
INSERT INTO t2(txt)
VALUES ('foo2'),('bar2'),('baz2');

CREATE TEMP TABLE t3 (id serial, txt text);

WITH x AS (
    UPDATE t1
    SET    txt = txt || '2'
    WHERE  txt ~~ 'ba%'
    RETURNING txt
    )
, y AS (
    DELETE FROM t2
    USING  x
    WHERE  t2.txt = x.txt
    RETURNING *
    )
INSERT INTO t3
SELECT *
FROM   y
RETURNING *;

请阅读手册中的Data-Modifying Statements in WITH一章。

答案 1 :(得分:1)

DECLARE
    r foo%rowtype;
BEGIN
    FOR r IN [COMPLEX QUERY]
    LOOP
    -- process r
    END LOOP;
    RETURN;
END