将 SQL 字符串传递给 oracle 存储过程并立即执行得到结果

Pass SQL string to oracle stored procedure and get results with execute immediate

我正在尝试将 SQL 字符串传递给存储过程并使用 EXECUTE IMMEDIATE 来 return 结果。像这样:

CREATE PROCEDURE P360_RCT_COUNT (sqlString IN VARCHAR2)
AS
BEGIN
   EXECUTE IMMEDIATE sqlString;
END;
/

我不确定如何完成它。综上所述,当我使用以下命令执行 SP 时,出现错误:

EXECUTE P360_RCT_COUNT 'SELECT COUNT(DISTINCT ENTITY_ID),ADDR_COUNTY FROM P360_V_RCT_COUNT GROUP BY ADDR_COUNTY';

错误是:ORA-06550:第 1 行,第 22 列:

PLS-00103: Encountered the symbol "SELECT COUNT(ENTITY_ID),ADDR_COUNTY FROM P360_V_RCT_COUNT GROUP " when expecting one of the following:

:= . ( @ % ; The symbol ":=" was substituted for "SELECT COUNT(DISTINCT ENTITY_ID),ADDR_COUNTY FROM P360_V_RCT_COUNT GROUP " to continue.

基本上,我在系统中构建一个 SQL 字符串,需要将其传递给 SP 并将结果返回给系统。我对 Oracle 中的存储过程比较陌生。

对于 return 个 OUT 参数中的值列表,您需要决定要使用的类型。

比如说,你必须 return 一些 varchar2 和一些 date 列表,你可以使用这样的东西:

create or replace type tabOfVarchar2 is table of varchar2(100);
create or replace type tabOfDates    is table of date;
create or replace procedure testProc(pString        IN     varchar2,
                                     pOutVarchar1      OUT tabOfVarchar2,
                                     pOutVarchar2      OUT tabOfVarchar2,
                                     pOutVarchar3      OUT tabOfVarchar2,
                                     pOutDates         OUT tabOfDates
                                    ) is
begin
    execute immediate pString
    bulk collect into pOutVarchar1, pOutVarchar2, pOutVarchar3, pOutDates;
end;

您可以通过这种方式测试此过程:

declare
    v1   tabOfVarchar2 ;
    v2   tabOfVarchar2;
    v3   tabOfVarchar2;
    d1   tabOfDates    ;
    vSQL varchar2(100)  := 'select ''a'', ''b'', ''c'', sysdate from dual';
begin
    testProc(vSQL, v1, v2, v3, d1);
    --
    for i in v1.first .. v1.last loop
        dbms_output.put_line(v1(i) || '/' || v2(i) || '/' || v3(i) || '/' || to_char(d1(i), 'dd/mm/yyyy'));
    end loop;
end; 

给出:

a/b/c/14/04/2017

这仅适用于准确给出固定数量的已知类型列的查询。

使用结果集的最简单方法是 sys_refcursor。这可以很容易地与 JDBC 或 ODBC 一起使用。

您的程序将如下所示:

CREATE PROCEDURE P360_RCT_COUNT (
       sqlString IN VARCHAR2
       , p_result_set out sys_refcursor)
AS
BEGIN
   open p_result_set for sqlString;
END;
/ 

显然,您如何称呼它的具体细节会因您的客户而异。但在 SQL*Plus 中它将是:

var rc refcursor
exec P360_RCT_COUNT( 'SELECT COUNT(DISTINCT ENTITY_ID),ADDR_COUNTY FROM P360_V_RCT_COUNT GROUP BY ADDR_COUNTY', :rc);
print rc