Oracle12C--動態SQL(60)

知識點的梳理:

  • 使用動態SQL可以在依賴對象不存在時創建子程序;
  • 動態SQL主要利用EXECUTE IMMEDIATE 語句執行DML,DDLDCL等語句操作;
  • 如果使用了綁定變量,則必須在EXECUTE IMMEDIATE中使用USING子句設置所需要的綁定變量;
  • 使用RETURNINGRETURN語句可以接收查詢或更新後的返回結果;
  • 使用批處理可以一次性將數據庫中取回的多個數據保存在集合中,或者使用FORALL將多個綁定參數設置到動態SQL中;

      

  • 動態SQL簡介
    • PL/SQL程序有一個特點:所操作的數據庫對象必須存在,否則創建的子程序會出現問題,這種操作被稱爲靜態SQL操作;
    • 動態SQL可讓用戶在定義程序時不指定具體的操作對象,在執行時動態傳入需要的數據庫對象,讓程序更加靈活;
      • 相對與靜態SQL,動態SQL在程序編譯時無法檢測數據對象是否存在,是否有指定的操作權限,只能等運行時才能發現這些錯誤;
    • Oracle構建動態SQL,可以使用NDSDBMS_SQL包兩種方式完成。在Oracle11g中,動態SQL的構建主要依靠NDS方式來完成,因爲NDS方式完成的動態SQL運行速度比DBMS_SQL包快,同時在NDS中也使用了比DBMS_SQL包中更簡單的語法:
      • NDS主要使用的是EXECUTE IMMEDIATE語句;
      • 處理多行數據,可用遊標,以及批量SQL
  • 舉個栗子
    • 示例1:利用動態SQL在執行時創建一張數據表

CREATE OR REPLACE FUNCTION get_table_count_fun(p_table_name VARCHAR2) RETURN NUMBER AS

v_sql_statement VARCHAR2(200) ; -- 定義操作的SQL語句

v_count NUMBER ; -- 保存表中記錄

BEGIN

SELECT COUNT(*) INTO v_count FROM user_tables WHERE table_name=UPPER(p_table_name) ;

IF v_count = 0 THEN -- 數據表不存在

v_sql_statement := 'CREATE TABLE ' || p_table_name ||

' ( id NUMBER ,

name VARCHAR2(30) NOT NULL ,

CONSTRAINT pk_id_' || p_table_name || ' PRIMARY KEY(id)) ' ; -- 創建數據表

EXECUTE IMMEDIATE v_sql_statement ; -- 執行動態SQL

END IF ;

v_sql_statement := 'SELECT COUNT(*) FROM ' || p_table_name ; -- 查詢數據表記錄

EXECUTE IMMEDIATE v_sql_statement INTO v_count ; -- 執行動態SQL並保存數據記錄

RETURN v_count ;

END ;

/

流程圖:

  • 接上例:編寫PL/SQL塊調用函數

BEGIN

DBMS_OUTPUT.put_line('數據表記錄:' || get_table_count_fun('mldnjava')) ;

END ;

/

本程序會直接輸出get_table_count_fun()函數的返回結果,在函數操作中,如果要操作的數據表不存在則會自動創建,本程序中輸入的mldnjava數據表不存在,執行後可以發現此表自動創建;

問題:在執行get_table_count_fun()函數時,可能會出現"ORA-01031:權限不足"錯誤:
該程序是在c
##scott用戶下執行的,但是默認情況下在c##scott.
get_table_count_fun()函數中無法創建數據表,此時需要將"CREATE ANY TABLE"的權限授予c##scott用戶,可執行如下sql語句:

CONN sys/change_on_install AS SYSDBA ;

GRANT CREATE ANY TABLE TO c##scott ;

CONN c##scott/tiger ;

授權之後,重新使用scott登錄,就可以正常使用get_table_count_fun()

  • 一些問題
    • 提示1:如果不使用EXECUTE IMMEDIATE,程序會出現錯誤
      • 下面的程序由於要操作的數據庫對象可能不存在,如果用戶直接使用DDLDML操作就會出現編譯錯誤;
      • 示例:直接在程序中編寫DDL或DML

CREATE OR REPLACE FUNCTION get_table_count_fun(p_table_name VARCHAR2) RETURN NUMBER AS

v_sql_statement                VARCHAR2(200) ;                        -- 定義操作的SQL語句

v_count                        NUMBER ;                        -- 保存表中記錄

BEGIN

SELECT COUNT(*) INTO v_count FROM user_tables WHERE table_name=UPPER(p_table_name) ;

IF v_count = 0 THEN                                        -- 數據表不存在

-- 錯誤:無法直接使用DDL操作

CREATE TABLE p_table_name (

id        NUMBER        ,

name        VARCHAR2(30)        NOT NULL ,

CONSTRAINT id_pk PRIMARY KEY(id)) ;

END IF ;

-- 錯誤:查詢數據表不存在

SELECT COUNT(*) INTO v_count FROM p_table_name ;

RETURN v_count ;

END ;

/

此時發現,在創建數據表的執行語句上出現了錯誤,這是因爲PL/SQL早期綁定特性,所以導致無法執行DDL

發佈了201 篇原創文章 · 獲贊 62 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章