Oracle入门(十四.18)之使用动态SQL
一、SQL的執行流程
數據庫中的所有SQL語句都經歷了不同的階段:?解析:預執行“這可能嗎?”檢查包括語法,對象存在,權限等
?綁定:獲取語句中引用的任何變量的實際值
?執行:語句被執行。
?提取:結果返回給用戶。
某些階段可能與所有語句無關;例如,提取階段適用于查詢,但不適用于DML。
二、PL / SQL子程序中SQL的執行流程
當PL / SQL子程序中包含SQL語句時,解析和綁定階段通常是在編譯時完成的,也就是說,當過程,函數或包體是CREATEd時。
如果在創建過程時SQL語句的文本未知,該怎么辦? Oracle服務器如何解析它? 它不能。 例如,假設您想要刪除一個表,但用戶在執行時輸入表名:
三、動態SQL
您使用動態SQL來創建一個SQL語句,其中的文本事先不完全知道。動態SQL:
?構造并存儲為子程序內的字符串。
?是否包含具有不同列數據的SQL語句,或帶有或不帶有占位符(綁定變量)的不同條件。
?使數據定義,數據控制或會話控制語句能夠從PL / SQL寫入和執行。
(1)本地動態SQL
PL / SQL不支持直接寫在procedure中的DDL語句。 本地動態SQL允許您通過在子程序中構建SQL并將其存儲為字符串來解決此問題。 本地動態SQL:?以PL / SQL語言直接為動態SQL提供本機支持。
?使數據定義,數據控制或會話控制語句能夠從PL / SQL寫入和執行。
?使用本機動態SQL語句(EXECUTE IMMEDIATE)或DBMS_SQL包執行。
?提供執行直到執行時間結構未知的SQL語句的能力。
?也可以使用OPEN-FOR,FETCH和CLOSE PL / SQL語句。
(2)使用EXECUTE IMMEDIATE語句
在PL / SQL匿名塊或子程序中為原生動態SQL使用EXECUTE IMMEDIATE語句:
EXECUTE IMMEDIATE dynamic_string [INTO {define_variable[, define_variable] ... | record}] [USING [IN|OUT|IN OUT] bind_argument[, [IN|OUT|IN OUT] bind_argument] ... ];?INTO用于單行查詢,并指定檢索列值的變量或記錄。?USING保存所有綁定參數。 如果未指定,則默認參數模式為IN。
?dynamic_string是包含SQL語句文本的字符變量或文字。
?define_variable是一個PL / SQL變量,用于存儲選定的列值。
?record是存儲選定行的用戶定義或%ROWTYPE記錄。
?bind_argument是一個表達式,其值在執行時傳遞給動態SQL語句。
?USING子句保存所有綁定參數。 默認參數模式是IN。
示例1:使用DDL語句的動態SQL
在線構建動態聲明:
CREATE PROCEDURE drop_any_table(p_table_name VARCHAR2) IS BEGINEXECUTE IMMEDIATE 'DROP TABLE '||p_table_name; END;在一個變量中構造動態語句:
CREATE PROCEDURE drop_any_table(p_table_name VARCHAR2) ISv_dynamic_stmt VARCHAR2(50); BEGINv_dynamic_stmt := 'DROP TABLE '||p_table_name;EXECUTE IMMEDIATE v_dynamic_stmt; END; BEGINdrop_any_table('EMPLOYEE_NAMES'); END;示例2:使用DML語句的動態SQL刪除任何表中的所有行并返回計數:
CREATE FUNCTION del_rows(p_table_name VARCHAR2) RETURN NUMBER IS BEGINEXECUTE IMMEDIATE 'DELETE FROM '||p_table_name;RETURN SQL%ROWCOUNT; END;調用該函數:
DECLAREv_count NUMBER; BEGINv_count := del_rows('EMPLOYEE_NAMES');DBMS_OUTPUT.PUT_LINE(v_count|| ' rows deleted.'); END;示例3:使用DML語句的動態SQL這是一個將行插入兩列并調用過程的示例。
CREATE PROCEDURE add_row(p_table_name VARCHAR2,p_id NUMBER, p_name VARCHAR2) IS BEGINEXECUTE IMMEDIATE 'INSERT INTO '||p_table_name||' VALUES (p_id, p_name)'; END; BEGIN add_row('EMPLOYEE_NAMES', 250, 'Chang'); END;示例4:使用本機動態SQL重新編譯PL / SQL代碼您可以使用下列ALTER語句重新編譯PL / SQL對象而不重新創建它們:
ALTER PROCEDURE procedure-name COMPILE; ALTER FUNCTION function-name COMPILE; ALTER PACKAGE package_name COMPILE SPECIFICATION; ALTER PACKAGE package-name COMPILE BODY;本示例創建一個過程,用于重新編譯在運行時輸入其名稱和類型的PL / SQL對象。
CREATE PROCEDURE compile_plsql (p_name VARCHAR2,p_type VARCHAR2,p_options VARCHAR2 := NULL) ISv_stmt VARCHAR2(200); BEGINv_stmt := 'ALTER '||p_type||' '||p_name||' COMPILE'||' '||p_options;EXECUTE IMMEDIATE v_stmt; END; BEGIN compile_plsql('MYPACK','PACKAGE','BODY'); END;四、使用DBMS_SQL包
(1)DBMS_SQL包的一些過程和功能是:? OPEN_CURSOR
? PARSE
? BIND_VARIABLE
? EXECUTE
? FETCH_ROWS
? CLOSE_CURSOR
(2)使用帶有DML語句的DBMS_SQL
刪除行的示例:
CREATE OR REPLACE FUNCTION del_rows (p_table_name VARCHAR2) RETURN NUMBER ISv_csr_id INTEGER;v_rows_del NUMBER; BEGINv_csr_id := DBMS_SQL.OPEN_CURSOR;DBMS_SQL.PARSE(v_csr_id,'DELETE FROM '||p_table_name, DBMS_SQL.NATIVE);v_rows_del := DBMS_SQL.EXECUTE (v_csr_id);DBMS_SQL.CLOSE_CURSOR(v_csr_id);RETURN v_rows_del; END;請將本文前面的內容與del_rows函數進行比較。 它們功能相同,但更簡單?
(3)使用帶有參數化DML語句的DBMS_SQL
再次,將其與本課前面的add_row過程進行比較。 你寧愿寫什么?CREATE PROCEDURE add_row (p_table_name VARCHAR2, p_id NUMBER, p_name VARCHAR2) ISv_csr_id INTEGER;v_stmt VARCHAR2(200);v_rows_added NUMBER; BEGINv_stmt := 'INSERT INTO '||p_table_name||' VALUES ('||p_id||','''||p_name||''')';v_csr_id := DBMS_SQL.OPEN_CURSOR;DBMS_SQL.PARSE(v_csr_id,v_stmt, DBMS_SQL.NATIVE);v_rows_added := DBMS_SQL.EXECUTE(v_csr_id);DBMS_SQL.CLOSE_CURSOR(v_csr_id); END;
五、本地動態SQL與DBMS_SQL包的比較
原生動態SQL
?比DBMS_SQL更易于使用
?比DBMS_SQL需要更少的代碼
?通常執行速度比DBMS_SQL快,因為執行的語句較少。
總結
以上是生活随笔為你收集整理的Oracle入门(十四.18)之使用动态SQL的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 乔思伯推出 D301 机箱:支持 MAT
- 下一篇: Oracle入门(十四.22)之创建DD