postgresql - 有条件地选择要在 FOR LOOP 中迭代的集合
问题描述
我想知道我是否可以在循环中执行 if-elsif 或 case-when。在 for 循环之间没有,但作为 for 循环的一个状态,可以在 select 或另一个之间进行选择。像这样的东西:
我已经尝试过 if-elsif 和 case-when ……但它们都没有奏效,我一直潜伏在网上寻找一些东西,但没有。
CREATE OR REPLACE FUNCTION myfunct(op integer, -vars-)
RETURNS table(-vars-)
LANGUAGE plpgsql
AS $function$
DECLARE
selectop record;
-vars-
BEGIN
FOR selectop in (IF (op=1) THEN
SELECT * FROM mytab WHERE somevar=true;
ELSIF (op=2) THEN
SELECT * from mytab WHERE somevar=false;
END IF;)
-things-
RETURN NEXT;
LOOP
---THINGS---
END;
$function$
解决方案
我想知道为什么你不只是设置一个变量并在查询中使用它。这似乎容易得多。但从学术的角度来看,这是一个有趣的问题。
问题是IF
或CASE
作为控制结构不返回某些东西或评估某些东西。所以我们不能以这种方式使用它们。
如果我们考虑返回一些东西,那么我们可能会想到函数。所以你可以在那里放置一个函数调用,它根据参数返回不同的集合。但似乎您想要的功能应该完全实现,所以这只会将问题转移到另一个层面并最终无限。
所以让我们考虑评估一些东西。表达式出现在我们的脑海中,确实有CASE
一个表达式,我们可以用它来切换。唯一的事情是,至少据我所知,它不能处理集合。
但它可以处理数组。所以这个想法是使用一个CASE
表达式,它计算为(两个)不同的数组。
我们将使用这样一个事实,即每个表还在 Postgres 中定义了一个类型,即其行的类型。所以我们将遍历该类型的数组。
Postgres 中的下一个巧妙的事情是,我们可以使用它array_agg()
来将完整的表或它的子集聚合到一个数组中。这就是我们将如何创建我们迭代的数组。
要遍历数组,我们将使用FOREACH
循环。(是的,这不是FOR
游标上的循环,但在语义上我猜这已经足够接近了。)
这样的函数可能如下所示。elbat
是我们的表和nmuloc4
我们想要比较值的列,具体取决于函数参数的值switch
。该函数返回一个SETOF elbat
,即来自 的一组记录elbat
。
CREATE FUNCTION noitcnuf
(switch integer)
RETURNS SETOF elbat
AS
$$
DECLARE
elbat_array elbat[];
elbat_element elbat;
BEGIN
FOREACH elbat_element IN ARRAY(CASE
WHEN switch = 1 THEN
(SELECT array_agg(elbat)
FROM elbat
WHERE nmuloc4 = true)
WHEN switch = 2 THEN
(SELECT array_agg(elbat)
FROM elbat
WHERE nmuloc4 = false)
ELSE
ARRAY[]::elbat[]
END) LOOP
RETURN NEXT elbat_element;
END LOOP;
RETURN;
END;
$$
LANGUAGE plpgsql;
在ELSE
分支中,CASE
我们只有一个正确类型的空数组。CASE
否则,如果我们将参数传递给在出口中没有分支的函数,我们会收到错误消息。像这样,我们只是在这种情况下得到空集。
请注意,这也适用于视图甚至可能是集合返回函数而不是表(我没有明确测试后者)。
但我也想警告一下,我怀疑这种方法的性能可能比仅仅根据变量构建查询并在游标上执行经典循环或最多将其减少为基于集合的方法而没有循环全部。
推荐阅读
- c++ - 从成员对象交互窗口组件
- javascript - 在html中请求图片后,three.js再次请求同一张图片
- google-play - Google Play 商店:退款的应用程序仍然可以使用和更新吗?
- c# - 无法正确循环发送短信,错误地向一个人发送多条短信
- c - 警告:从不兼容的指针类型初始化 [-Wincompatible-pointer-types]
- c++ - 具有静态数据成员的对象的不同实例 - 可能吗?
- python - 在 python 3 中将 pdf 文件读取到文本文件,但会生成类似 AttributeError: 'PDFObjRef' object has no attribute 'decode' 的错误
- css - HTML表格布局中的中心内容
- android - 在Android中更改图像填充颜色
- c++ - 未实现赋值运算符时调用构造函数