开发者

How do I pass a list of numbers into a stored procedure?

开发者 https://www.devze.com 2023-02-16 17:00 出处:网络
So I have the following stored procedure: CREATE OR REPLACE PROCEDURE stored_p ( ntype IN NUMBER, p_ResultSet OUTTYPES.cursorType

So I have the following stored procedure:

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

and, I can call it like this:

VARIABLE resultSet  REFCURSOR
EXEC stored开发者_高级运维_p(80001, :resultSet);
PRINT :resultSet

but I want to be able to call it like this:

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

How should I modify my stored procedure accordingly? I am doing this so that I can display the results in a Crystal Report... (just in case that affects anything).. Thanks!!


The best option would be to pass a collection

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

Unfortunately, Crystal Reports may not be able to pass a proper collection to a stored procedure. If that is the case, you'd have to pass in a comma-separated list of numbers. Your procedure would then have to parse that comma-separated string into a collection. You can use (or modify) Tom Kyte's in_list function for this

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


Newer versions might have different options. I work some with Oracle 9 and 10, and I will typically pass in a string of comma-separated values and dynamically build the SQL. There are some significant dangers with SQL injection to be aware of, though.


You need to create a type..

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
)

You can loop it using..

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

To test it,

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


   stored_p(ntypetest,..)

There may be some variation in syntax.

Of course you can pass in comma separated values too but that will come in as a string. Your string should be something like 'val1','val2','val3'. You need to be careful when you have numbers as the whole string will look like in ('2343,3444,2222') which will be treated as one value instead of multiple numbers as in (2343,3444,2222)

0

精彩评论

暂无评论...
验证码 换一张
取 消