Oracle EXECUTE IMMEDIATE с переменным количеством возможных Привязок?

мне нужно использовать динамическое выполнение SQL в Oracle, где я не знаю точное количество переменных привязки, используемых в SQL до выполнения.

есть ли способ использовать переменное число переменных привязки в вызове EXECUTE IMMEDIATE почему?

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

я попробовал что-то вроде

EXECUTE IMMEDIATE 'SELECT SYSDATE FROM DUAL WHERE :var = :var' USING 1;

но он откинулся назад с ORA-01008: not all variables bound.

5 ответов


вы не можете сделать это с помощью EXECUTE IMMEDIATE. Однако вы можете сделать это с помощью Oracle DBMS_SQL пакета. The руководство разработчика приложений для баз данных имеет сравнение между EXECUTE IMMEDIATE вы знакомы с and dbms_sql методы. на этой странице документы DBMS_SQL, но есть некоторые примеры (связанные выше), которые должны заставить вас начать (Пример 1-простой случай запуска оператора, который может иметь произвольное количество переменных привязки). DBMS_SQL много больше громоздко с точки зрения кодирования, но это позволит вам сделать почти все, что вы можете себе представить.

допускается несколько экземпляров переменной bind, встречающихся в SQL. Однако вам нужно будет знать имя, используемое в качестве переменной bind (например,: var в вашем случае), чтобы передать его в DBMS_SQL.BIND_VARIABLE.


вы также можете обойти эту проблему, используя WITH заявление. Как правило, используя DBMS_SQL лучше, но иногда это проще так:

BEGIN
    EXECUTE IMMEDIATE 'WITH var AS (SELECT :var FROM dual) SELECT SYSDATE FROM DUAL WHERE (SELECT * FROM var) = (SELECT * FROM var)' USING 1;
END;

этой нить на AskTom ответы на все ваши вопросы.

в вашем случае, если вы хотите передать один параметр или нет, вы можете создать два запроса с одним параметром и в один из этих запросов не используется (т. е. предикат всегда правда) такой:

-- query1
SELECT * FROM DUAL WHERE dummy = :x;

-- query2
SELECT * FROM DUAL WHERE nvl(:x, 1) IS NOT NULL;

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


более конкретно, мне нужно передать один параметр в неизвестность SQL, но я не знаю, как часто он будет использоваться там.

Я на самом деле столкнулся с этой же проблемой пару дней назад, и друг поделился со мной способом сделать то, что с EXECUTE IMMEDIATE.

Он включает в себя создание блока PLSQL в отличие от самого блока SQL. При использовании EXECUTE IMMEDIATE с блоком кода PLSQL, вы можете связывать переменные по имени, а не только позиция.

проверьте мой пример / код и мой собственный аналогичный вопрос / ответ:


можно использовать dbms_sql Как объяснил Стив Броберг, но результирующий курсор нельзя использовать (читать) во многих клиентах. Oracle 11 добавил функцию преобразования (dbms_sql.to_refcursor), что позволяет преобразовать dbms_sql курсор к курсору ref, но по какой-то причине нельзя использовать этот преобразованный курсор ref в приложении .Net. Можно использовать обычный курсор ref в .net, но не курсор ref, который раньше был dbms_sql курсор.

так какой клиент будет потребляете этот курсор?