将数组作为参数传递到Oracle存储过程

时间:2012-12-05 18:55:54

标签: php oracle stored-procedures

我有点腌渍。我有一个存储过程接受一个参数并返回一个查询的结果。该查询使用IN语句。

这是SP的结构:

CREATE OR REPLACE 
PROCEDURE EXAMPLE_SP
(
   arg VARCHAR2,
   argRS1 OUT cursors.rs
)
AS 
 l_test VARCHAR2(255) := arg;

BEGIN

  OPEN argRS1 FOR
    SELECT * FROM TABLE1
    WHERE LOCATION IN (l_test);

END EXAMPLE_SP;

IN语句中的值的数量可以是可变的。 IN的选项来自UI侧的选定表单复选框。

我正在使用PHP来检索所选的复选框值。我已经尝试将值插入到逗号分隔的字符串中。

我的逻辑是查询看起来像这样:

l_test = 'val1,  val2, val3';
SELECT * FROM TABLE1
WHERE LOCATION IN (val1, val2, val3);

但那没用。我不知道该怎么办。提前感谢任何建设性意见或建议。

4 个答案:

答案 0 :(得分:0)

您可以将此逗号分隔的输入参数添加为varchar()并使用以下where语句:

where (','||l_test||',' like '%,'||LOCATION||',%')

例如,如果我们得到l_test='2,3,4,5'LOCATION=3

where (',2,3,4,5,' like '%,3,%') 

如果LOCATION值在此列表中,则为TRUE。

答案 1 :(得分:0)

我认为您选择的位置是VARCHAR,因此您需要转换列表,如下所示

l_test = '''val1''||','|| ''val2''||','||''val3''';

这样您的最终查询就像

SELECT * FROM TABLE1
WHERE LOCATION IN ('val1', 'val2', 'val3');

你也可以这样做

CREATE OR REPLACE 
PROCEDURE EXAMPLE_SP
(
  arg VARCHAR2,
  argRS1 OUT cursors.rs
)
AS 
 l_test VARCHAR2(255) := arg;

 BEGIN
  l_test:=''''||replace(l_test,',',''',''')||'''';
  OPEN argRS1 FOR
    SELECT * FROM TABLE1
     WHERE LOCATION IN (l_test);

 END EXAMPLE_SP;

注意:我没有对此进行测试,但我认为这样你就可以达到你想要的效果

答案 2 :(得分:0)

我会在不使用字符串操作的情况下执行此操作。从理论上讲,SQL注入的风险目前可能很小,因为你使用的是复选框,最好在开始时实施好的练习,所以如果有任何改变,你就不会让自己处于危险之中。

第二个好处是您仍然可以使用列上的任何索引,如果使用like '%...,则无法使用这些索引。

要执行此操作,您可以使用表格函数和外部对象来填充“输入”列表。

作为示例,我将从USER_OBJECTS返回OBJECT_NAME。

如果我创建两个表:

create table tmp_test ( a number );
create table tmp_test2 ( a number );

和一个用于保存表格列表的对象,或者在您的案例位置。

create type t_test_object is table of varchar2(30);

接下来,这是相当于您的程序。它是一个返回SYS_REFCURSOR的函数。它接受T_TEST_OBJECT作为参数,这意味着首先需要在传递给函数之前填充它。

create or replace function select_many (
       Ptest_object in t_test_object
       ) return sys_refcursor is

   l_curs sys_refcursor;

begin

   open l_curs for
    select object_name
      from user_objects
     where object_name in ( select *
                              from table(Ptest_object)
                                   );

   return l_curs;

end;

最后,这是一个如何使用此设置的示例。请注意T_TEST_OBJECT的实例如何填充多个值。然后该对象被传递给函数以返回光标。最后,显示值循环光标的值。显然,您可能希望使用光标并以不同方式填充TYPE。

SQL> declare
  2
  3     l_nested_table t_test_object := new t_test_object();
  4     l_cursor sys_refcursor;
  5     -- Used for display demonstration only.
  6     l_object_name user_objects.object_name%type;
  7
  8  begin
  9
 10     l_nested_table.extend;
 11     l_nested_table(l_nested_table.last) := 'TMP_TEST';
 12     l_nested_table.extend;
 13     l_nested_table(l_nested_table.last) := 'TMP_TEST2';
 14
 15     l_cursor := select_many(l_nested_table);
 16     
 17     loop -- Display example, not really relevant
 18        fetch l_cursor into l_object_name;
 19        exit when l_cursor%notfound;
 20        dbms_output.put_line(l_object_name);
 21     end loop;
 22
 23  end;
 24  /
TMP_TEST
TMP_TEST2

PL/SQL procedure successfully completed.

答案 3 :(得分:0)

您可以使用Oracle文档中的Oracle示例:http://docs.oracle.com/cd/B28359_01/win.111/b28378/basfeat.htm#sthref207

看这里 - 返回一张桌子: Can an SQL procedure return a table?

这是另一个例子:

PACKAGE emp_actions IS
  TYPE EnameTabTyp IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER;
  TYPE SalTabTyp IS TABLE OF emp.sal%TYPE INDEX BY BINARY_INTEGER;
  ...
  PROCEDURE hire_batch (ename_tab IN EnameTabTyp, sal_tab IN SalTabTyp, ...);
  PROCEDURE log_names (ename_tab IN EnameTabTyp);
END emp_actions;