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
курсор.
так какой клиент будет потребляете этот курсор?