Function PL/pgSQL代码的问题

Function PL/pgSQL代码的问题,function,postgresql,cursor,plpgsql,dynamic-sql,Function,Postgresql,Cursor,Plpgsql,Dynamic Sql,我在plpgsql方面不是很有经验,所以我这里有两个问题 在Postgres中是否可以像在动态sql for plsql中那样使用游标?基本上,我不想在plsql中使用过程,所以我创建了一个游标,它将保存动态查询的输出,然后我在另一个查询中的循环中使用该值,以使我的输出显示在屏幕上。同样的事情,我正试图与博士后,但不能这样做。 在这种情况下,是否有可能避免创建永久性功能来完成此任务? 以下是我运行良好的oracle脚本: DECLARE CURSOR cur_tables IS S

我在plpgsql方面不是很有经验,所以我这里有两个问题

在Postgres中是否可以像在动态sql for plsql中那样使用游标?基本上,我不想在plsql中使用过程,所以我创建了一个游标,它将保存动态查询的输出,然后我在另一个查询中的循环中使用该值,以使我的输出显示在屏幕上。同样的事情,我正试图与博士后,但不能这样做。 在这种情况下,是否有可能避免创建永久性功能来完成此任务? 以下是我运行良好的oracle脚本:

DECLARE
  CURSOR cur_tables IS
     SELECT  NAME,
'SELECT PROPERTY_VALUE FROM '
         || USERNAME
         || '.P_PROPERTY WHERE PROPERTY_NAME = ''VERSION'''
                 AS dsql
       FROM CB_DATASOURCE
      WHERE (UPPER(USERNAME) LIKE 'NAV_PS_%' or UPPER(USERNAME) LIKE 'CBPS_%' or UPPER(USERNAME) LIKE 'DEFAULTPS');
  CURR_VERSION VARCHAR2(1000);
BEGIN
  FOR r_tables IN cur_tables LOOP
   begin
     EXECUTE IMMEDIATE r_tables.dsql INTO CURR_VERSION;
     DBMS_OUTPUT.put_line(r_tables.NAME || ': ' || CURR_VERSION);
    exception
     when others then
      DBMS_OUTPUT.put_line(r_tables.NAME || ' no table');
   end;   
  END LOOP;
END;
/
这是我的postgres函数,我无法让它工作,但最终我想避免使用永久函数

create or replace function upgrade_version() returns setof record as $$ 
declare
 r record;
 loopy record;
 isql text;
 CURR_VERSION text;
begin
 for r in SELECT 'SELECT PROPERTY_VALUE FROM '
         || USERNAME
         || '.P_PROPERTY WHERE PROPERTY_NAME = ''VERSION'''
                 AS dsql
       FROM CB_DATASOURCE
      WHERE (UPPER(USERNAME) LIKE 'NAV_PS_%' or UPPER(USERNAME) LIKE 'CBPS_%' or UPPER(USERNAME) LIKE 'DEFAULTPS') loop
  isql := r.dsql;
  EXECUTE isql INTO CURR_VERSION;
  RETURN next loopy;
 end loop;
 return;
end;
$$ language 'plpgsql';

我非常感谢您在这方面的任何意见。

您可以通过使用DO$$$脚本避免创建永久函数:

但是,我不清楚如何避免完全使用PL/pgSQL代码,因为您是基于另一个查询的内容定义游标的。您正在Oracle中使用PL/SQL代码;为什么在PostgreSQL中不需要过程代码

如果您对游标有偏好,您当然可以在PL/pgSQL函数中使用OPEN CURSOR FOR EXECUTE,但不能使用Oracle中的相同结构;在PL/pgSQL中,不能将游标声明为字符串替换。这仅在打开时执行:


除了为每个用户提供一个EAV设置表不是一个很好的设计之外…

您似乎要尝试的应该是:

要点 您不能从DO语句返回,但可以发出通知等。 似乎非常适合您,因为您最终希望避免使用永久函数。 请注意,DO语句的默认过程语言仍然是plpgsql

在Postgres中,不带引号的标识符被转换为小写,而Oracle是大写的

要捕获循环中的异常,需要将主体包装在单独的块中

您需要清理动态构建的SQL字符串中的标识符,以免易受SQL注入和其他非标准名称问题的影响。您的Oracle代码也缺少。 为此,我正在使用带有%I的格式。更多信息:

将WHERE子句缩短为

您知道uu是类似模式中的占位符字符吗?对于文字\,将其转义为:\ \


过程语言的名称为。RDBMS的名称是。至少你可以自己发现。请提出一个适当的问题,不要害怕。谢谢你的意见。下一次,我会尝试提出一个体面的问题。旁白:不要在语言plpgsql中引用语言名称。它是一个标识符,不是字符串。暂时可以容忍,但在未来的版本中可能会消失。
DO
$do$ 
DECLARE
   r record;
   curr_version text;
BEGIN
   FOR r IN 
      SELECT name, format($$
         SELECT property_value
         FROM   %I.p_property
         WHERE  property_name = 'VERSION'$$, username) AS dsql
      FROM   cb_datasource
      WHERE  upper(username) LIKE ANY ('{NAV_PS_%, CBPS_%, DEFAULTPS}')
   LOOP
      BEGIN
         EXECUTE r.dsql INTO curr_version;
         RAISE NOTICE '%: %', r.name, curr_version;
      EXCEPTION WHEN OTHERS THEN
         RAISE NOTICE '%: no table', r.name;
      END;   
   END LOOP;
END
$do$