Как передать список чисел в хранимую процедуру? - PullRequest
4 голосов
/ 11 марта 2011

Итак, у меня есть следующая хранимая процедура:

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 ... (на всякий случай, если это повлияет на что-либо) .. Спасибо !!

Ответы [ 3 ]

10 голосов
/ 11 марта 2011

Лучшим вариантом будет передать коллекцию

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 может не передать надлежащую коллекцию хранимой процедуре.Если это так, вы должны будете указать список чисел через запятую.Ваша процедура должна была бы проанализировать эту строку через запятую в коллекцию.Вы можете использовать (или изменить) функцию 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 голосов
/ 11 марта 2011

Вам нужно создать тип ..

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)

0 голосов
/ 11 марта 2011

Более новые версии могут иметь разные параметры.Я работаю с Oracle 9 и 10 и обычно передаю строку значений, разделенных запятыми, и динамически собираю SQL.Однако следует помнить о некоторых значительных опасностях, связанных с внедрением SQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...