バインド変数は、DDLステートメントでは許可されていません。したがって、次のステートメントはエラーを引き起こします:
-
例1:DDLステートメント 。 ORA-01027が発生します:データ定義操作で変数をバインドできません
EXECUTE IMMEDIATE 'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT :def_val )' USING 42;
-
例2:DDLステートメント 。 ORA-00904::無効な識別子
が発生しますEXECUTE IMMEDIATE 'CREATE TABLE dummy_table ( :col_name NUMBER )' USING var_col_name;
-
例3:SCLステートメント 。 ORA-02248が発生します:ALTER SESSION
のオプションが無効ですEXECUTE IMMEDIATE 'ALTER SESSION SET NLS_CALENDAR = :cal' USING var_calendar_option;
問題
これが発生する理由を理解するには、動的SQLステートメントの処理方法を確認する必要があります。
通常、アプリケーションプログラムは、SQLステートメントのテキストとステートメントで使用されるホスト変数の値の入力をユーザーに求めます。次に、OracleはSQLステートメントを解析します。つまり、OracleはSQLステートメントを調べて、SQLステートメントが構文規則に従い、有効なデータベースオブジェクトを参照していることを確認します。解析には、データベースのアクセス権の確認も含まれます 、必要なリソースを予約し、最適なアクセスパスを見つけます。
回答者によって追加された強調
解析ステップは前に行われることに注意してください 変数を動的ステートメントにバインドします。上記の4つの例を調べると、バインド変数の値を知らなければ、パーサーがこれらの動的SQLステートメントの構文上の妥当性を保証する方法がないことがわかります。
- 例1 :パーサーは、バインド値が有効かどうかを判断できません。
USING 42
の代わりに 、プログラマーはUSING 'forty-two'
を作成しました ? - 例2 :パーサーは
:col_name
かどうかを判断できません 有効な列名になります。バインドされた列名が'identifier_that_well_exceeds_thirty_character_identifier_limit'
だった場合はどうなりますか ? - 例3 :
NLS_CALENDAR
の値 組み込みの定数です(特定のOracleバージョンに対して?)。パーサーは、バインドされた変数に有効な値があるかどうかを判断できません。
したがって、答えは、動的SQLではテーブル名や列名などのスキーマ要素をバインドできないということです。また、組み込みの定数をバインドすることもできません 。
ソリューション
スキーマ要素/定数の参照を動的に実現する唯一の方法は、動的SQLステートメントで文字列連結を使用することです。
-
例1:
EXECUTE IMMEDIATE 'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT ' || to_char(42) || ')';
-
例2:
EXECUTE IMMEDIATE 'CREATE TABLE dummy_table (' || var_col_name || ' NUMBER )';
-
例3:
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_CALENDAR = ''' || var_calendar_option || '''';