【问题标题】:dynamic query in oracle procedure using cursororacle过程中使用游标的动态查询
【发布时间】:2013-03-03 08:48:46
【问题描述】:

我正在使用存储过程来使用游标选择记录。此过程获取记录 ID 作为输入。

代码如下:

create or replace
procedure GET_ITEM_DETAILS_ALL
(
  cur_out out sys_refcursor,
  PSTRING VARCHAR2 DEFAULT NULL
)
is
  query_string  VARCHAR2(1000);
Begin
  query_string := 'Select IT.SL_NO from ITEM_DETAILS IT where IT.SL_NO in (:sl) order by IT.SL_NO';
  OPEN cur_out FOR query_string USING PSTRING;
End;

为了调用/测试程序,我使用以下代码:

VAR R REFCURSOR
EXEC GET_ITEM_DETAILS_ALL (:R, '4')
PRINT R 

问题是当我传递一个整数,例如'4'或'2'时,程序返回数据,但当我传递'1,2'或'3,4'时,它显示错误。

【问题讨论】:

    标签: oracle dynamic procedure


    【解决方案1】:
       OPEN cur_out FOR Select IT.SL_NO from ITEM_DETAILS IT where IT.SL_NO in (SELECT REGEXP_SUBSTR(sl,'[^,]+', 1, LEVEL) FROM DUAL CONNECT BY REGEXP_SUBSTR(sl, '[^,]+', 1, LEVEL) IS NOT NULL ) order by IT.SL_NO
    

    【讨论】:

      【解决方案2】:

      问题是 PSTRING 是单个变量而不是数组。所以你的陈述实际上等同于

      .... where IT.SL_NO = PSTRING
      

      这就是为什么它在您通过 4 时有效,而在您通过 1,2 时失败。

      以您的方式使用动态 SQL 没有任何价值(我们可以在不使用字符串的情况下打开引用游标)。但是,利用动态 SQL 是解决问题的一种方法:

      query_string := 'Select IT.SL_NO from ITEM_DETAILS IT where IT.SL_NO in ('
                         ||PSTRING||
                         ') order by IT.SL_NO';
      OPEN cur_out FOR query_string;
      

      或者,您可以使用字符串标记器将字符串转换为标记。不幸的是,Oracle 没有内置标准,但对于不同版本的数据库有各种解决方法。阿德里安比灵顿有a good round-up on his site。使用其中一种方法可以让您放弃动态 SQL:

      OPEN cur_out FOR select IT.SL_NO from ITEM_DETAILS IT 
         where IT.SL_NO in ( select * from table ( your_string_tokenizer( PSTRING ) ) ) 
         order by IT.SL_NO;
      

      【讨论】:

        【解决方案3】:

        您不能使用一个绑定变量将值列表传递给查询。
        传递带有逗号分隔列表的字符串后,您的查询变为
        Select IT.SL_NO from ITEM_DETAILS IT where IT.SL_NO in ('1,2') order by IT.SL_NO
        这是不正确的。
        您应该手动将输入字符串转换为查询中的值列表。

        【讨论】:

          【解决方案4】:

          解决方法如下:

          create or replace procedure GETITEM_DETAILS_ALL
          
          (
              cur_out out sys_refcursor,
              PSTRING VARCHAR2 DEFAULT NULL
           )
          
          is
          
          query_string  VARCHAR2(1000);
          
          Begin
          
          query_string := 'Select IT.SL_NO from ITEM_DETAILS IT where IT.SL_NO in (' || PSTRING || ') order by IT.SL_NO';
          
          OPEN cur_out FOR query_string;
          
          End;
          

          【讨论】:

            猜你喜欢
            • 2021-01-14
            • 1970-01-01
            • 1970-01-01
            • 2014-03-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-10-20
            • 2015-04-05
            相关资源
            最近更新 更多