web-dev-qa-db-ja.com

PL / SQLでの動的SELECT INTO句を使用したバインド変数の使用

PL/SQLの動的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;
/

このような選択ステートメントでバインド変数を使用できるかどうか疑問に思っていました

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リファレンスを読んでみましたが、このような選択の例はありません。

ありがとう

42
BYS2

いいえ、バインド変数をそのように使用することはできません。 2番目の例では、:into_bindv_query_strは、変数v_num_of_employeesの値の単なるplaceholderです。 select intoステートメントは次のようになります。

SELECT COUNT(*) INTO  FROM emp_...

v_num_of_employeesの値はEXECUTE IMMEDIATEnullであるためです。

最初の例は、戻り値を変数にバインドする正しい方法を示しています。

編集

元のポスターは、デフォルトのOUTモードの代わりにv_num_of_employeesINパラメーターモードを使用するように私の回答で参照している2番目のコードブロックを編集しました。この変更により、両方の例は機能的に同等になります。

27
user272735

私の意見では、動的PL/SQLブロックはやや不明瞭です。非常に柔軟性がありますが、調整もデバッグも難しく、何が起きているのかを把握するのも困難です。私の最初の選択肢は投票です。

EXECUTE IMMEDIATE v_query_str INTO v_num_of_employees USING p_job;

どちらもバインド変数を使用しますが、私にとっては、最初に@jonearlesオプションよりも再利用可能および調整可能です。

27
Aitor

選択文を動的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;
/
19
Jon Heller

バインド変数は、 "in"句を使用してOracle SQLクエリで使用できます。

10gで動作します。他のバージョンについては知りません。

バインド変数は、最大4000文字のvarcharです。

例:コンマ区切りの値のリストを含むバインド変数。

: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句を指定するにはどうすればよいですか?

0
Kat