web-dev-qa-db-ja.com

PL / SQLブロックに直接ddlステートメントを書き込めないのはなぜですか

PL/SQLブロックに直接ddlステートメントを記述できないのはなぜですか(たとえば、

CREATE OR REPLACE PROCEDURE test IS
BEGIN
    truncate table table_name; // error
END test;
/

だが、

CREATE OR REPLACE PROCEDURE test IS
BEGIN
    execute immediate 'truncate table table_name'; // works fine
END test;
/

なぜ2つ目が正常に実行されたのですか?

11
Ravi

ドキュメント にあるように:

PL/SQLプログラム単位内で次のタイプの文を実行できるのは、動的SQLのみです。

  • CREATE、DROP、GRANT、REVOKEなどのデータ定義言語(DDL)ステートメント

TRUNCATE操作はDDLです。

EXECUTE IMMEDIATEを使用する場合、実行するDDL操作は暗黙的に現在のトランザクションをCOMMIT実行することに注意してください。

7
Philᵀᴹ

PL/SQLコード内のDDLは、実際の必要性よりも例外です。解析は構造検証と見なすことができ、構造が実行時に変更されると失われます。プロシージャは、他のオブジェクト(テーブル、または他のpl/sqlコード、ビューなど)を再度解析することを目的としています。依存オブジェクトが変更されるたびに、再コンパイルする必要があります。したがって、構造の変更以外の解析済みコードを作成することは検証できず、コンパイルもできません。ケースを検討する

DROP TABLE T1;

解析時にテーブルが見つかり、プロシージャが正常にコンパイルされますが、最初の実行時にテーブルが削除され、コードが無効になります(次回DROP TABLEがエラーになる)。同様に、テーブルDDLを変更すると、再コンパイルが必要になるため、コード解析の利点が失われます。

1
igr