将SQL字符串传递给oracle存储过程并使用execute immediate获取结果

时间:2017-04-14 11:40:56

标签: sql oracle stored-procedures dynamic-sql

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

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:遇到符号" SELECT COUNT(ENTITY_ID),ADDR_COUNTY   来自P360_V_RCT_COUNT GROUP"期待以下之一:

     

:=。 (@%;符号":="代替" SELECT   来自P360_V_RCT_COUNT GROUP的COUNT(DISTINCT ENTITY_ID),ADDR_COUNTY"至   继续。

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

2 个答案:

答案 0 :(得分:1)

要返回OUT参数中的值列表,您需要确定要使用的类型。

比方说,例如,您必须返回一些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

这仅适用于提供已知类型的固定数量的列的查询。

答案 1 :(得分:1)

使用结果集的最简单方法是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