Oracle

為什麼我們不能直接將 ddl 語句寫入 PL/SQL 塊

  • August 24, 2020

為什麼我們不能直接在 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;
/

為什麼第二個成功執行?

正如文件中所說:

只有動態 SQL 才能在 PL/SQL 程序單元中執行以下類型的語句:

  • 數據定義語言 (DDL) 語句,例如 CREATE、DROP、GRANT 和 REVOKE

一個TRUNCATE操作是DDL

使用 時EXECUTE IMMEDIATE,請記住DDL您執行的任何操作都將隱含地執行COMMIT目前事務。

答案是 PL/SQL 不支持動態多態性。它只支持靜態多態,因為

所有 PL/SQL 都會為 Ada 生成一個“DIANA”-> Descriptive Intermediate Attributed Notation,這是一種樹形結構的中間語言。編譯器在內部使用 DIANA。

在編譯時,PL/SQL 原始碼被翻譯成系統程式碼並生成相應的 DIANA。現在想想如果有一個像 create table 語句這樣的 DDL 語句在編譯時不存在,它將在執行程序後創建。那麼您的 PL/SQL 引擎將如何生成 DIANA 呢????

DIANA 在 PL/SQL 中起著重要的作用,用於檢查/驗證子程序。這是必需的,因為我們知道子程序可以使用數據庫對象,例如表、視圖、同義詞或其他儲存過程。下次執行程序時,對象可能已更改/刪除/丟棄。例如:有人可能刪除了表,儲存的過程或函式簽名可能已更改。

這就是為什麼通常使用 PL/SQL 來操縱數據庫結構中的數據,而不是操縱那些結構的原因。

但是有一些方法可以使用動態 SQL 和 DBMS_SQL 包進行操作,但這些方法再次應謹慎使用。例如,如果你正在創建一個表,你應該首先檢查這個表是否已經存在或者沒有使用數據字典視圖。連結- https://stackoverflow.com/questions/15232252/why-is-static-ddl-not-allowed-in-pl-sql

引用自:https://dba.stackexchange.com/questions/37362