Использование переменных связывания с динамическим предложением SELECT INTO в PL / SQL - PullRequest
42 голосов
/ 19 октября 2011

У меня есть вопрос относительно того, где переменные связывания могут использоваться в динамическом операторе 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 в качестве двоичной строки и использовал переменную связывания в предложении INTO.

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

Спасибо

Ответы [ 5 ]

27 голосов
/ 19 октября 2011

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

EXECUTE IMMEDIATE v_query_str INTO v_num_of_employees USING p_job;

Оба используют переменные связывания, но, во-первых, для меня это более пригодно для настройки и настройки, чем опция @jonearles.

27 голосов
/ 19 октября 2011

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

SELECT COUNT(*) INTO  FROM emp_...

, потому что значение v_num_of_employees равно null при EXECUTE IMMEDIATE.

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

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

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

19 голосов
/ 19 октября 2011

Поместите оператор выбора в динамический блок 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;
/
0 голосов
/ 27 декабря 2016

Функция «Выбрать в» работает только для PL / SQL Block, когда вы используете «Выполнить немедленно», oracle интерпретирует v_query_str как строку SQL-запроса, поэтому вы не можете использовать в .will get ключевое слово отсутствует исключение.в примере 2 мы используем начало и конец;таким образом это стало pl / sql блоком и его законным.

0 голосов
/ 11 июня 2016

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

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

Переменная связывания 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 в динамическом запросе с использованием переменной? )

...