我对plpgsql不是很有经验,所以我在这里有2个问题。
这是我运行正常的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';
我真的很感激这方面的任何意见。
答案 0 :(得分:4)
您似乎在尝试使用DO
statement:
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$
RETURN
声明无法DO
,但您可以RAISE
通知等。
从eventually would like to refrain from using a permanent function
开始,似乎对你来说是完美的
请注意,DO
语句的默认过程语言仍为plpgsql
。
在Postgres中,不带引号的标识符被转换为小写(而不是Oracle,它们是大写的)。
要捕获循环中的异常,您需要将主体包装在单独的块中。 Read the manual here.
您需要清理动态生成的SQL字符串中的标识符,以免易受SQL注入和非标准名称的其他问题的影响。您的Oracle代码也缺乏。
我将format()
与%I
用于此目的。更多信息:
How to use EXECUTE FORMAT ... USING in postgres function
使用ANY
WHERE
条款
您知道_
是LIKE
模式中的占位符吗?对于文字_
,请将其转义:\_
。
答案 1 :(得分:3)
您可以使用DO $$ $$脚本避免创建永久功能:http://www.postgresql.org/docs/9.3/static/sql-do.html
但是,我不清楚你是如何完全避免使用PL / pgSQL代码的,因为你根据另一个查询的内容定义了一个游标。您在Oracle中使用PL / SQL代码;为什么你不需要PostgreSQL中的程序代码?
如果您偏好游标,您当然可以在PL / pgSQL函数中使用OPEN CURSOR FOR EXECUTE,但是您不能使用与Oracle相同的结构;在PL / pgSQL中,您不能将游标作为字符串替换进行DECLARE。这只是在OPEN期间完成的:http://www.postgresql.org/docs/9.3/static/plpgsql-cursors.html
除了认为每个用户都有一个EAV设置表并不是一个很棒的设计......