PL/SQL использует табличную переменную в предложении Where

У меня есть табличная переменная, которая передается в процедуру. Я хотел бы использовать значения в предложении where, как показано ниже, как мне это сделать. Первая строка ниже объявлена ​​в определении пакета. Процедура ниже находится в теле пакета.

type CatalogNos is table of VARCHAR2(100);
PROCEDURE GET_PART_CHARACTERISTICS (v_catalog_nos_  IN CatalogNos, 
                                    Parts_Char_Cursor out sys_refcursor) AS
BEGIN
    OPEN Parts_Char_Cursor FOR
    SELECT * FROM IFSAPP.SALES_PART_CHARACTERISTIC
    WHERE CATALOG_NO IN (select values from v_catalog_nos_);
END GET_PART_CHARACTERISTICS;

person Adam    schedule 28.12.2011    source источник


Ответы (3)


Является ли CatalogNos типом SQL (т.е. не объявленным в спецификации пакета)? Если так:

PROCEDURE GET_PART_CHARACTERISTICS (v_catalog_nos_  IN CatalogNos, 
                                    Parts_Char_Cursor out sys_refcursor) 
AS
BEGIN
    OPEN Parts_Char_Cursor FOR
    SELECT * FROM IFSAPP.SALES_PART_CHARACTERISTIC
    WHERE CATALOG_NO IN (select * from table(v_catalog_nos_));
END GET_PART_CHARACTERISTICS;

«Этот SQL выдает ошибку: PLS-00642: локальные типы коллекций не разрешены в операторах SQL»

Таким образом, CatalogNos не является типом SQL, т.е. это тип PL/SQL, объявленный в спецификации или теле пакета. Сообщение об ошибке совершенно ясно: мы не можем использовать типы PL/SQL в операторах SQL. Так оно и есть.

Самое простое решение — использовать тип SQL.

SQL> create or replace type CatalogNos is table of VARCHAR2(100);    
  2  /

Type created.

SQL> 

Если вы действительно не хотите создавать свой собственный тип (почему бы и нет?), вы можете использовать один из встроенных модулей Oracle. Так:

create or replace PROCEDURE GET_PART_CHARACTERISTICS
      (v_catalog_nos_  IN sys.dbms_debug_vc2coll,
       Parts_Char_Cursor out sys_refcursor)
AS
BEGIN
    OPEN Parts_Char_Cursor FOR
    SELECT * FROM IFSAPP.SALES_PART_CHARACTERISTIC
    WHERE CATALOG_NO IN (select * from table(v_catalog_nos_));
END GET_PART_CHARACTERISTICS;
/
person APC    schedule 28.12.2011
comment
Этот SQL выдает ошибку: PLS-00642: локальные типы коллекций не разрешены в операторах SQL. - person Adam; 29.12.2011

create type CatalogNos is table of VARCHAR2(100);

CREATE OR REPLACE PACKAGE your_package as
   PROCEDURE GET_PART_CHARACTERISTICS (v_catalog_nos_  IN CatalogNos, 
                                       Parts_Char_Cursor out sys_refcursor);
END your_package;

CREATE OR REPLACE PACKAGE BODY your_package as
   PROCEDURE GET_PART_CHARACTERISTICS (v_catalog_nos_  IN CatalogNos, 
                                       Parts_Char_Cursor out sys_refcursor) AS
   BEGIN
       OPEN Parts_Char_Cursor FOR
       SELECT * FROM IFSAPP.SALES_PART_CHARACTERISTIC
       WHERE CATALOG_NO IN (select column_value from table(v_catalog_nos_));
   END GET_PART_CHARACTERISTICS;
END your_package;

Определение типа должно быть объектом базы данных, а не частью пакета, чтобы его можно было использовать в SQL. Как только это верно, вы можете использовать функцию table для ссылки на переменную этого типа в предложении from.


Судя по комментарию, мне кажется, что мне нужно повторить итерацию: чтобы сослаться на пользовательский тип данных в SQL, вы должны определить тип как отдельный объект вне пакета.


Для определяемой пользователем таблицы, содержащей одно безымянное поле, можно использовать либо select *, либо select column_value.

person Allan    schedule 28.12.2011
comment
Если ваша первая строка в моем определении пакета, то пакет не будет компилироваться. - person Adam; 29.12.2011
comment
СОЗДАЙТЕ ИЛИ ЗАМЕНИТЕ ПАКЕТ BODY - person Florin Ghita; 29.12.2011
comment
Хорошо, все это работает, за исключением ключевого слова values ​​в операторе IN. Он компилируется, если я заменю его *. - person Adam; 29.12.2011

Используйте || для объединения вашего запроса с переменной

что-то типа:

type CatalogNos is table of VARCHAR2(100);
PROCEDURE GET_PART_CHARACTERISTICS (v_catalog_nos_  IN CatalogNos, 
                                Parts_Char_Cursor out sys_refcursor) AS
BEGIN
   OPEN Parts_Char_Cursor FOR
   'SELECT * FROM IFSAPP.SALES_PART_CHARACTERISTIC
   WHERE CATALOG_NO IN (select values from' || v_catalog_nos_ || ')';
END GET_PART_CHARACTERISTICS;
person Emmanuel N    schedule 28.12.2011
comment
Я все еще получаю ошибки компиляции... ORA-00936: отсутствует выражение, указывающее на начало значений. - person Adam; 29.12.2011
comment
& используется SQL*Plus только на стороне клиента для определения (интерактивных) параметров. Это не будет работать во время выполнения внутри хранимой процедуры. - person a_horse_with_no_name; 29.12.2011
comment
Вы действительно пробовали это? Oracle не может ссылаться на определяемый пользователем тип таблицы без использования функции table. Это предлагаемое решение не будет работать. Кроме того, даже если это сработает, конкатенация значения переменной в операторе DML является крайне плохой практикой. - person Allan; 29.12.2011