2011-03-11 89 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)

相關問題