Как проверить наличие условия IN для динамического списка в Oracle? - PullRequest
2 голосов
/ 11 августа 2010

РЕДАКТИРОВАТЬ: изменил заголовок в соответствии с кодом ниже.

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

Я пытался сделать это с помощью курсоров (как показано ниже), но это не удалось.

DECLARE
    TYPE gcur IS REF CURSOR;
    TYPE list_record IS TABLE OF my_table.my_field%TYPE;
    c_GENERIC gcur;
    c_LIST list_record;
BEGIN
    OPEN c_GENERIC FOR
    SELECT my_field FROM my_table
    WHERE some_field = some_value;

    FETCH c_GENERIC BULK COLLECT INTO c_LIST;

    -- try to check against list
    SELECT * FROM some_other_table
    WHERE some_critical_field IN c_LIST;

END

По сути, я пытаюсь кешировать список допустимых значений в переменную, потому что позже я буду неоднократно проверять его.

Как вы выполняете это в Oracle?

Ответы [ 2 ]

4 голосов
/ 12 августа 2010

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

create type list_record is table of varchar2(128)
/

Это потому, что мы не можем использовать типы PL / SQL в инструкциях SQL. Увы, это означает, что мы не можем использовать %TYPE или %ROWTYPE, потому что они являются ключевыми словами PL / SQL.

Ваша процедура будет выглядеть так:

DECLARE
    c_LIST list_record;
BEGIN

    SELECT my_field 
    BULK COLLECT INTO c_LIST 
    FROM my_table
    WHERE some_field = some_value;

    -- try to check against list
    SELECT * FROM some_other_table
    WHERE some_critical_field IN ( select * from table (c_LIST);

END;    

"Я вижу, что вам все еще приходилось выполнять Оператор SELECT для заполнения списка для предложения IN. "

Если значения находятся в таблице, нет другого способа получить их в переменную:)

"Я думаю, что есть значительный прирост производительности при использовании это через прямое полусоединение "

Не обязательно. Если вы используете значения только один раз, то подзапрос, безусловно, является лучшим подходом. Но поскольку вы хотите использовать одни и те же значения в ряде дискретных запросов, заполнение коллекции является более эффективным подходом.

В версии 11g Enterprise Edition мы можем использовать кэширование набора результатов . Это гораздо лучшее решение, но оно подходит не для всех таблиц.

1 голос
/ 11 августа 2010

Зачем тянуть список вместо использования полусоединения?

SELECT * 
  FROM some_other_table 
 WHERE some_critical_field IN (SELECT my_field 
                                FROM my_table
                               WHERE some_field = some_value); 
...