PostgreSQL循环是否可以在函数外部执行?

13

我正在比较PostgreSQL和SQLServer以便进行迁移。现在我正在评估T-SQL vs. 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 中,没有必要将其放在函数或过程中。我可以这样做吗?

在网上搜索时,我发现在 MySQL 中不可以这样做(负面答案),但我没有找到有关 Postgres 的类似答案。

2个回答

31

不能DECLARE(全局)变量(有解决方法),也不能使用纯SQL循环,除了由@bma提供的递归CTE(严格来说是对行进行迭代,而不是循环)。

然而,有DO语句用于这种即席过程代码。自Postgres 9.0引入以来,它的工作方式类似于一次性函数,但不接受任何参数,也不返回任何内容。您可以RAISE通知等,所以您的示例将正常工作:

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。但是,您可以使用任何已注册的过程语言,只要您声明它(例如:LANGUAGE plpython)。
此外,Postgres还提供generate_series()以临时生成集合,这可能会避免许多情况下需要循环的情况。在此处尝试搜索示例。 此外,您可以在普通SQL中的数据修改CTE中使用WHERE子句来分叉情况并模拟IF .. THEN .. ELSE .. END...

1
值得强调的是,如果您能够将问题重新表述为集合而不是循环,请务必这样做 - 也就是说,如果您能够构建一个可以一次处理结果的SQL查询,它很可能比使用过程化代码更高效。 - IMSoP

3

非常感谢您,bma。但我可以使用Declare关键字吗?因为有时候你需要插入例如,或者根据某些条件进行插入,如果条件为真则插入else if... update... else delete... 我表达清楚了吗? 最好的问候。 - JGutierrezC
2
不是使用“Declare”,而是使用WITH子句,您可以在顶部子句中提交一个值,并在查询的后续位置多次引用它(也称为“链接”)。例如,在我提供的链接中,“regional_sales”部分被用作后续部分(名为“top_regions”)的源。这说明了我提到的查询链接。在Postgresql 9.2+中,您可以使用WITH子句(也称为“公共表达式”(CTE))执行“upsert”语句(您称之为“insert inf true,else update,else delete”)。 - bma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接