2011-03-11 88 views
4

所以,我有以下存储过程:如何将数字列表传递到存储过程?

CREATE OR REPLACE PROCEDURE stored_p 
(
ntype IN NUMBER   , 
p_ResultSet OUT TYPES.cursorType 
) 
AS 
BEGIN 
OPEN p_ResultSet FOR 
select * from table where ttype in ntype; 
END stored_p 

,而且我可以这样调用:

VARIABLE resultSet REFCURSOR 
EXEC stored_p(80001, :resultSet); 
PRINT :resultSet 

,但我希望能这样称呼它:

VARIABLE resultSet REFCURSOR 
EXEC stored_p([80001,80002], :resultSet); 
PRINT :resultSet 

我该如何修改我的存储过程?我正在这样做,以便我可以在Crystal Report中显示结果...(以防万一会影响任何内容)。谢谢!

回答

9

最好的办法是通过收集

SQL> create type empno_tbl 
    2 is 
    3 table of number; 
    4/

Type created. 


SQL> create or replace procedure stored_p 
    2 (
    3 empnos in empno_tbl, 
    4 p_rc out sys_refcursor) 
    5 as 
    6 begin 
    7 open 
    8 p_rc for select * from emp where empno in (select * from table(empnos)); 
    9 end; 
10/

Procedure created. 

SQL> var rc refcursor; 

SQL> ed 
Wrote file afiedt.buf 

    1 create or replace procedure stored_p 
    2 (
    3 empnos in empno_tbl, 
    4 p_rc out sys_refcursor) 
    5 as 
    6 begin 
    7 open 
    8 p_rc for select * from emp where empno in (select * from table(empnos)); 
    9* end; 
SQL> begin 
    2 stored_p(new empno_tbl(7902,7934), :rc); 
    3 end; 
    4/

PL/SQL procedure successfully completed. 

SQL> print rc 

    EMPNO ENAME  JOB    MGR HIREDATE   SAL  COMM 
---------- ---------- --------- ---------- --------- ---------- ---------- 
    DEPTNO FAKE_COL  FOO 
---------- ---------- ---------- 
     7902 FORD  ANALYST   7566 03-DEC-81  3000 
     20   1 

     7934 MILLER  CLERK   7782 23-JAN-82  1300 
     10   1 

不幸的是,Crystal Reports可能无法将正确的集合传递给存储过程。如果是这样的话,你必须传递一个以逗号分隔的数字列表。然后,您的过程必须将该逗号分隔的字符串解析为集合。您可以使用(或修改)Tom Kyte's in_list功能

SQL> ed 
Wrote file afiedt.buf 

    1 create or replace function in_list(
    2  p_string in varchar2 
    3 ) 
    4  return empno_tbl 
    5 as 
    6  l_string  long default p_string || ','; 
    7  l_data   empno_tbl := empno_tbl(); 
    8  n    number; 
    9 begin 
10  loop 
11   exit when l_string is null; 
12   n := instr(l_string, ','); 
13   l_data.extend; 
14   l_data(l_data.count) := 
15    ltrim(rtrim(substr(l_string, 1, n-1))); 
16   l_string := substr(l_string, n+1); 
17  end loop; 
18  return l_data; 
19* end; 
SQL>/

Function created. 

SQL> ed 
Wrote file afiedt.buf 

    1 create or replace procedure stored_p 
    2 (
    3 empnos in varchar2, 
    4 p_rc out sys_refcursor) 
    5 as 
    6 begin 
    7 open p_rc 
    8  for select * 
    9   from emp 
10   where empno in (select * 
11       from table(in_list(empnos))); 
12* end; 
SQL>/

Procedure created. 

SQL> ed 
Wrote file afiedt.buf 

    1 begin 
    2 stored_p('7902,7934', :rc); 
    3* end; 
SQL>/

PL/SQL procedure successfully completed. 

SQL> print rc 

    EMPNO ENAME  JOB    MGR HIREDATE   SAL  COMM 
---------- ---------- --------- ---------- --------- ---------- ---------- 
    DEPTNO FAKE_COL  FOO 
---------- ---------- ---------- 
     7902 FORD  ANALYST   7566 03-DEC-81  3000 
     20   1 

     7934 MILLER  CLERK   7782 23-JAN-82  1300 
     10   1 
0

较新版本可能有不同的选项。我使用Oracle 9和10工作,并且通常会传入一串以逗号分隔的值并动态构建SQL。尽管如此,SQL注入还是有一些重大的危险。

1

你需要创建一个类型..

create or replace type NUMBER_ARRAY as table of number; 

CREATE OR REPLACE PROCEDURE stored_p 
(
ntype IN NUMBER_ARRAY   , 
p_ResultSet OUT TYPES.cursorType 
) 

可以循环使用它..

for i in 1 .. ntype.count 
loop 
    dbms_output.put_line(ntype(i)); 
end loop; 

为了测试它,

DECLARE 
    ntypetest      NUMBER_ARRAY := NUMBER_ARRAY(); 
BEGIN 
    FOR i IN 1 .. 5 
    LOOP 
     ntypetest.EXTEND; 
     ntypetest (i) := i; 
    END LOOP; 


    stored_p(ntypetest,..) 

可能有一些变化句法。

当然,您也可以传递逗号分隔值,但是会以字符串形式传入。你的字符串应该是'val1','val2','val3'。你必须要小心,当你有一个数字作为整个字符串像in ('2343,3444,2222')这将被视为一个值,而不是多个号码作为in (2343,3444,2222)

相关问题