【问题标题】:Should I use Plpgsql to loop through table instead of using SQL?我应该使用 Plpgsql 来循环遍历表而不是使用 SQL 吗?
【发布时间】:2021-12-05 03:01:40
【问题描述】:

我有一项工作每天晚上运行,将更改加载到临时表中并将这些更改应用到主表。

CREATE TEMP TABLE IF NOT EXIST tmp AS SELECT * FROM mytable LIMIT 0;

COPY tmp FROM PROGRAM '';

11 SQL queries to update 'mytable' based on data from 'tmp'

我有大量查询要从 tmp 中删除重复项、更新 tmp 中的值、更新主表中的值以及将新行插入主表中。是否可以使用 plpgsql 循环遍历两个表?

UPDATE mytable m
    SET "Field" = t."Field" +1
FROM tmp t
WHERE (t."ID" = m."ID");

在这个例子中,它是一个列值的简单改变。相反,我想对主表和临时表进行更复杂的操作。

编辑:所以这里有一些我想象的伪代码。

LOOP tmp t, mytable m
BEGIN
-- operation in plpgsql including UPDATE, INSERT, DELETE
END
WHERE t.ID = m.ID;

【问题讨论】:

  • 是的,只需将您现在正在运行的查询按正确的顺序放入函数中即可。
  • 在切换到plpgsql语言之前先尝试创建sql user-defined functionsql user-defined procedure
  • 我已经将查询放入了一个过程中并且它确实有效,但它似乎对我来说效率低下,因为我必须执行很多查询并且我需要执行更复杂的操作我需要添加更多查询。所以我在想的是我是否可以有一个嵌套的循环。
  • 你当然可以在 psql 和循环中得到你想要的东西。但是您说“但对我来说似乎效率低下...”,您可能要记住,涉及 SQL 的循环通常是效率最低的方法有。
  • 感谢您的反馈。编程背景和没有 SQL 经验往往会使您根据程序定义解决方案。我能够减少查询的数量以使其更可口。在 UPDATE 查询中使用函数计算值有多糟糕?

标签: postgresql plpgsql


【解决方案1】:

您可以使用 plpgsql FOR 来loop over query results

DECLARE
    myrow RECORD;
BEGIN
    FOR myrow IN SELECT * FROM table1 JOIN table2 USING (id)
    LOOP
       ... do something with the row ...
    END LOOP;
END

如果您想在循环遍历表的同时更新表,您可以创建一个FOR UPDATE 游标,但如果查询是连接,这将不起作用,因为这样您就不会在表上打开更新游标.

注意写入/更新临时表比写入普通表要快得多,因为临时表没有 WAL 和崩溃恢复开销,而且它们由一个连接拥有,因此您不必担心锁。

如果你把一个查询放在循环中,它会被执行很多次,这可能会变得很慢。使用批量查询通常更快,即使它们很复杂。

如果您想用依赖于其他表和连接的值更新临时表中的许多行,使用不同的连接和 WHERE 条件在临时表上运行多次更新可能会更快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-07
    • 1970-01-01
    • 2014-12-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多