Использование переменных привязки с динамическим предложением SELECT INTO в PL / SQL

у меня есть вопрос о том, где переменные Привязки могут использоваться в динамической инструкции SQL в PL/SQL.

например, я знаю, что это действует:

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER
IS
  v_query_str VARCHAR2(1000);
  v_num_of_employees NUMBER;
BEGIN
  v_query_str := 'SELECT COUNT(*) FROM emp_' 
                 || p_loc
                 || ' WHERE job = :bind_job';                           
  EXECUTE IMMEDIATE v_query_str
    INTO v_num_of_employees
    USING p_job;
  RETURN v_num_of_employees;
END;
/

мне было интересно, можете ли вы использовать переменные привязки в операторе select, как это

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER
IS
  v_query_str VARCHAR2(1000);
  v_num_of_employees NUMBER;
BEGIN
  v_query_str := 'SELECT COUNT(*) INTO :into_bind FROM emp_' 
                 || p_loc
                 || ' WHERE job = :bind_job';                           
  EXECUTE IMMEDIATE v_query_str
    USING out v_num_of_employees, p_job;
  RETURN v_num_of_employees;
END;
/

Примечание. я использовал оператор SELECT INTO в качестве моей строки dyamic и использовал переменную bind в предложении INTO.

в настоящее время я путешествую прямо сейчас и не буду иметь доступа к моему компьютеру вернулся домой на несколько дней, но это меня немного беспокоит. Пробовал читать ссылку PL/SQL, но у них нет примера такого выбора.

спасибо

5 ответов


нет, вы не можете использовать переменные связывания, таким образом. Во втором примере :into_bind на v_query_str это просто местозаполнитель значение переменной v_num_of_employees. Ваше заявление select into превратится во что-то вроде:

SELECT COUNT(*) INTO  FROM emp_...

потому что значение v_num_of_employees is null at EXECUTE IMMEDIATE.

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

редактировать

оригинальный плакат отредактировал второй блок кода, на который я ссылаюсь в своем ответе, чтобы использовать OUT режим параметр для v_num_of_employees вместо IN режим. Эта модификация делает оба примера функционально эквивалентны.


на мой взгляд, динамический блок PL/SQL несколько неясен. В то время как очень гибкий, также трудно настроить, трудно отлаживать и трудно понять, что происходит. Мой голос идет к вашему первому варианту,

EXECUTE IMMEDIATE v_query_str INTO v_num_of_employees USING p_job;

как использование переменных связывания, но во-первых, для меня redeable и особенности чем вариант @jonearles.


поместите инструкцию select в динамический блок PL/SQL.

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER
IS
  v_query_str VARCHAR2(1000);
  v_num_of_employees NUMBER;
BEGIN
  v_query_str := 'begin SELECT COUNT(*) INTO :into_bind FROM emp_' 
                 || p_loc
                 || ' WHERE job = :bind_job; end;';
  EXECUTE IMMEDIATE v_query_str
    USING out v_num_of_employees, p_job;
  RETURN v_num_of_employees;
END;
/

переменная Bind может использоваться в запросе Oracle SQL с предложением "in".

работает в 10g; я не знаю о других версиях.

переменная Bind-это varchar до 4000 символов.

пример: привязка переменной, содержащей список значений, разделенных запятыми, например

:bindvar = 1,2,3,4,5

select * from mytable
  where myfield in
    (
      SELECT regexp_substr(:bindvar,'[^,]+', 1, level) items
      FROM dual
      CONNECT BY regexp_substr(:bindvar, '[^,]+', 1, level) is not null
    );

(та же информация, что и здесь:Как указать предложение IN в динамическом запросе с помощью переменной? )


Select Into functionality работает только для блока PL/SQL, когда вы используете Execute immediate , oracle интерпретирует v_query_str как строку SQL-запроса, поэтому вы не можете использовать into .получит ключевое слово missing Exception. в Примере 2 мы используем begin end; поэтому он стал блоком pl/sql и его законным.