【问题标题】:How to pass multiple values into one parameter in stored procedure (Oracle)如何将多个值传递给存储过程中的一个参数(Oracle)
【发布时间】:2020-07-13 09:28:01
【问题描述】:

我为存储过程创建了一个参数,希望允许用户传入多个输入。

create procedure sp1 (p1 in varchar2)
as
begin
 select proc_id from proc_tbl where proc_id in (p1);
end;

用户希望在 p1 中输入多个以逗号或空格分隔的值,例如 a1、b2、c3。 proc_tbl中存储的所有PROC_ID都是大写的。

sp 没有成功运行并将输入作为一个完整的字符串。

在普通的 sql in 子句中,我们可以这样输入

select proc_id from proc_tbl where proc_id in ('A1', 'B2', 'C3')

我们如何在不区分大小写的情况下在 oracle sp 中应用相同的逻辑?

【问题讨论】:

标签: sql oracle stored-procedures plsql parameters


【解决方案1】:

从数据库的角度来看,作为参数给出的 csv 列表只是另一个字符串,而不是值列表。所以你不能使用IN。

一种简单的方法是使用正则表达式函数:

select proc_id from proc_tbl where regexp_like(p1, '^|,' || proc_id || ',|$', 'i');

正则表达式的意思是:

  • proc_id 位于参数字符串的开头(^)或以逗号开头
  • AND:proc_id 位于参数字符串的末尾 ($) 或后跟逗号

【讨论】:

  • 这个查询非常有用,但它以某种方式返回表中的所有 proc_id 而不是指定的 p1 参数值。
【解决方案2】:

从 SQL 注入的角度来看,您可能希望将某种类型的集合作为参数。或者至少扫描输入以查找保留字。但在那之后,您可以像这样使用您的字符串作为动态 SQL 的一部分:

create procedure sp1 (p1 in varchar2)
as
  TYPE lt_ResultTable is TABLE OF proc_table.proc_id%TYPE;
  l_tResult lt_ResultTable;
  l_nResult proc_table.proc_id%type;
begin
 EXECUTE IMMEDIATE 'select proc_id from proc_tbl where proc_id in ('||p1||')'
  BULK COLLECT INTO l_tResult;
 /*If you are guaranteed only one row will return from your query, you don't need to use a 
  nested table 
 EXECUTE IMMEDIATE 'select proc_id from proc_tbl where proc_id in ('||p1||')' INTO l_nResult;
*/
end;

【讨论】:

    【解决方案3】:

    没有 INTO 子句的简单选择甚至无法编译。但是,有一种方法可以安全地在一个参数中传递多个值:

    create or replace procedure sp1(p1 in varchar2) is
    begin
    for r in (
        select xt.proc_id
        from proc_tbl pt, xmltable(p1 columns proc_id varchar2(100) path '.') xt
        where pt.proc_id = xt.proc_id
    )
    loop
        dbms_output.put_line(r.proc_id);
    end loop;
    end;
    /
    

    【讨论】:

      【解决方案4】:

      如果您可以控制参数,那么在字符串中使用集合而不是逗号分隔的列表会更加健壮。您可以创建自己的集合或使用其中一个预建集合。

      架构

      --drop table proc_tbl;
      create table proc_tbl(proc_id number);
      insert into proc_tbl values(1);
      insert into proc_tbl values(2);
      insert into proc_tbl values(3);
      

      程序

      --SYS.ODCINUMBERLIST is defind as a VARRAY(32767) OF NUMBER.
      --Or you could create your own type, like: create type number_tab as table of number;
      create or replace procedure sp1 (p1 in sys.odcinumberlist) as
          v_count number;
      begin
          select count(*)
          into v_count
          from proc_tbl
          where proc_id in (select column_value from table(p1));
      
          dbms_output.put_line('Count: '||v_count);
      end;
      /
      

      示例调用

      begin
          sp1(sys.odcinumberlist(1,2));
      end;
      /
      
      Result
      ------
      Count: 2
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-01
        • 2011-07-12
        • 1970-01-01
        相关资源
        最近更新 更多