【问题标题】:PostgreSQL loops outside functions. Is that possible?PostgreSQL 在函数外循环。那可能吗?
【发布时间】:2013-08-22 20:25:46
【问题描述】:

出于迁移目的,我正在比较 PostgreSQL 与 SQLServer。现在我正在评估 T-SQL 与 PL/pgSQL,问题是在 T-SQL 中您可以使用循环或声明变量,例如:

declare @counter int
set @counter = 0
while @counter < 10
begin
   set @counter = @counter + 1
   print 'The counter is ' + cast(@counter as char)
end

没有必要把它放在函数或过程中。我可以在 PostgreSQL 中这样做吗?

在网上搜索我发现negative answer 在 MySQL 中执行此操作,但我没有为 Postgres 找到这样的答案。

【问题讨论】:

    标签: tsql function postgresql loops plpgsql


    【解决方案1】:

    不能DECLARE(全局)变量(there are workarounds)也不能使用普通SQL循环 - 除了recursive CTEs as provided by @bma(实际上是迭代行,严格来说不是循环)。

    然而,有DO statement 用于此类临时程序代码。与 Postgres 9.0 一起引入。它像一次性函数一样工作,但不接受任何参数,也不返回任何内容。你可以RAISEnotices 等,所以你的例子可以正常工作:

    DO
    $do$
    DECLARE
       _counter int := 0;
    BEGIN
       WHILE _counter < 10
       LOOP
          _counter := _counter + 1;
          RAISE NOTICE 'The counter is %', _counter;  -- coerced to text automatically
       END LOOP;
    END
    $do$
    

    如果没有另外指定,正文中的语言默认为plpgsql。你可以使用any registered procedural language,如果你声明它(比如:LANGUAGE plpython)。

    Postgres 还提供generate_series() 来生成临时集合,这可以避免在许多情况下循环的需要。 Try a search here on SO for examples.

    此外,您可以在纯 SQL 中的 data-modifying CTE 中使用 WHERE 子句来分叉案例并模拟 IF .. THEN .. ELSE .. END ...

    【讨论】:

    • 值得更强烈地重申如果您可以根据集合而不是循环重新提出您的问题,那么就这样做 - 也就是说,如果您可以构建 SQL 查询一次就可以处理结果,它的性能可能比诉诸程序代码要好得多。
    【解决方案2】:

    假设您使用的是 Postgresql 8.4+,您可以使用 WITH RECURSIVE 递归查询结果集。文档:http://www.postgresql.org/docs/current/static/queries-with.html

    这将允许您循环您的集合并以各种方式处理数据。

    【讨论】:

    • 非常感谢 bma。但是我可以使用 Declare 关键字吗?因为有时您需要插入例如,或者如果条件为真则根据某些条件插入 else if... update... else delete... 我清楚了吗?最好的问候。
    • "Declare",不,但是使用 WITH 子句,您可以在最上面的子句之一中提交一个值,并在查询的后续位置多次引用该值(也称为“链接”)。例如,在我提供的链接中,“regional_sales”部分用作后续部分(名为“top_regions”)的来源。这说明了我提到的查询链接。在 Postgresql 9.2+ 中,您可以使用 WITH 子句(又名“通用表表达式”(CTE))来执行“upsert”语句(您称之为“insert inf true, else update, else delete”)
    猜你喜欢
    • 2023-03-27
    • 1970-01-01
    • 2013-04-15
    • 2022-07-27
    • 1970-01-01
    • 2017-04-08
    • 2013-03-23
    • 1970-01-01
    • 2021-06-15
    相关资源
    最近更新 更多