Oracle

初級 PL/SQL:從動態 SQL 函式返回行值

  • January 16, 2017

我有一個成功編譯的 PL/SQL 函式:

01    WITH FUNCTION find_CV_errors(
02        l_table_name IN VARCHAR
03        ,l_field_name IN VARCHAR
04        ,l_domain_name IN VARCHAR
05        ) 
06        RETURN VARCHAR
07        AS
08        l_return_value VARCHAR(128);
09    BEGIN
10    
11    EXECUTE IMMEDIATE
12        'SELECT 
13            LISTAGG(CAST(' || l_field_name || ' AS VARCHAR(50)),  ' ||  ''';  ''' || ') WITHIN GROUP (ORDER BY NULL)
14        FROM ' ||
15            l_table_name ||
16        ' LEFT JOIN 
17            (
18            SELECT CODE
19            FROM  ENG.D_CV_ENG_VW
20            WHERE DOMAIN = :bv1
21            )
22        ON ' || l_field_name || '  = code
23        WHERE ' ||
24            l_field_name || ' IS NOT NULL
25            AND code IS NULL'
26    INTO l_return_value
27    USING l_domain_name;
28    RETURN  l_return_value;               
29    END;

該函式有一個動態 sql 查詢,通過 LISTAGG 在單行中輸出單列。

我希望函式將動態 sql 輸出作為返回值返回。但是,現在它只返回 NULL,因為我沒有為l_return_value變數賦值。

如何將動態 SQL 查詢的輸出分配給l_return_value變數?

更新#1:

我已添加INTO l_return_value;到查詢 ( LINE 26),但現在出現錯誤:

ORA-06553:PLS-103: Encountered the symbol "L_FIELD_NAME" when expecting one of the following: : = , ( @ % ;

更新#2:

當我從 末尾刪除分號時line 26,該函式返回 的值l_field_name,而不是來自動態 sql 查詢輸出的值。

更新#3:

除了 Balazs Papp 指出的錯誤之外,我還有一個綁定變數 on line 13,而實際上我應該使用連接變數。由於 Balazs Papp 的回答使用了通用範例,而不是問題的更正版本,因此我自己更正了原始問題(lines 07, 13, 26, 27, 28)。

對於單行,使用EXECUTE IMMEDIATE ... INTO. 一個簡單的例子:

set serveroutput on
declare
 l_result number;
begin
 execute immediate 'select count(*) from dual' into l_result;
 dbms_output.put_line(l_result);
end;
/

1

對於多行,請使用EXECUTE IMMEDIATE .. BULK COLLECT INTO,這是一個範例:

https://stackoverflow.com/questions/21117021/bulk-collect-into-and-execute-immediate-in-oracle

declare
  type x is table of t.id%type index by pls_integer;
  xx x;
 begin
  execute immediate
  'select id from t' bulk collect into xx;
  dbms_output.put_line(xx.count);
end;
/

好的,另一個例子,使用 12c WITH 函式:

with function f1 (p_a number) return number
as
 l_result number;
begin
 execute immediate 'select count(*) from dba_objects where object_id = :B1' 
 into l_result
 using p_a;
 return l_result;
end;
select f1(object_id) from dba_objects where object_name = 'HELP';
/

F1(OBJECT_ID)
-------------
           1

引用自:https://dba.stackexchange.com/questions/161243