oracle 開發中動態SQL的使用方法sql
通常的PL/SQL程序設計中,在DML和事務控制的語句中能夠直接使用SQL,可是DDL語句及系統控制語句卻不能在PL/SQL中直接使用,要想實如今PL/SQL中使用DDL語句及系統控制語句,能夠經過使用動態SQL來實現。數據庫
首先咱們應該瞭解什麼是動態SQL,在Oracle數據庫開發PL/SQL塊中咱們使用的SQL分爲:靜態SQL語句和動態SQL語句。所謂靜態SQL指在PL/SQL塊中使用的SQL語句在編譯時是明確的,執行的是肯定對象。而動態SQL是指在PL/SQL塊編譯時SQL語句是不肯定的,如根據用戶輸入的參數的不一樣而執行不一樣的操做。編譯程序對動態語句部分不進行處理,只是在程序運行時動態地建立語句、對語句進行語法分析並執行該語句。oracle
Oracle中動態SQL能夠經過本地動態SQL來執行,也能夠經過DBMS_SQL包來執行。下面就這兩種狀況分別進行說明:函數
1、本地動態SQL測試
本地動態SQL是使用EXECUTE IMMEDIATE語句來實現的。spa
一、本地動態SQL執行DDL語句:.net
需求:根據用戶輸入的表名及字段名等參數動態建表。設計
create or replace procedure proc_test
(
table_name in varchar2 , -- 表名
field1 in varchar2 , -- 字段名
datatype1 in varchar2 , -- 字段類型
field2 in varchar2 , -- 字段名
datatype2 in varchar2 -- 字段類型
) as
str_sql varchar2 ( 500 );
begin
str_sql: = ' create table ' || ' ' || table_name || ' ( ' || field1 || ' ' || datatype1 || ' , ' || field2 || ' ' || datatype2 || ' ) ' ;
execute immediate str_sql; -- 動態執行DDL語句
exception when others then
null ;
end ; 對象
以上是編譯經過的存儲過程代碼。下面執行存儲過程動態建表。事務
SQL > execute proc_test( ' dinya_test ' , ' id ' , ' number(8) not null ' , ' name ' , ' varchar2(100) ' );
PL / SQL procedure successfully completed
SQL > desc dinya_test;
Name Type Nullable Default Comments
-- -- ------------- -------- ------- --------
ID NUMBER ( 8 )
NAME VARCHAR2 ( 100 ) Y
SQL >
到這裏,就實現了咱們的需求,使用本地動態SQL根據用戶輸入的表名及字段名、字段類型等參數來實現動態執行DDL語句。
二、本地動態SQL執行DML語句。
需求:將用戶輸入的值插入到上例中建好的dinya_test表中。
create or replace procedure proc_insert
(
id in number , -- 輸入序號
name in varchar2 -- 輸入姓名
) as
str_sql varchar2 ( 500 );
begin
str_sql: = ' insert into dinya_test values(:1,:2) ' ;
execute immediate str_sql using id,name; -- 動態執行插入操做
exception when others then
null ;
end ;
執行存儲過程,插入數據到測試表中。
SQL > execute proc_insert( 1 , ' dinya ' );
PL / SQL procedure successfully completed
SQL > select * from dinya_test;
ID NAME
1 dinya
在上例中,本地動態SQL執行DML語句時使用了using子句,按順序將輸入的值綁定到變量,若是須要輸出參數,能夠在執行動態SQL的時候,使用RETURNING INTO 子句,如:
declare
p_id number : = 1 ;
v_count number ;
begin
v_string: = ' select count(*) from table_name a where a.id=:id ' ;
execute immediate v_string returning into v_count using p_id;
end ;
2、使用DBMS_SQL包
使用DBMS_SQL包實現動態SQL的步驟以下:
A、先將要執行的SQL語句或一個語句塊放到一個字符串變量中。
B、使用DBMS_SQL包的parse過程來分析該字符串。
C、使用DBMS_SQL包的bind_variable過程來綁定變量。
D、使用DBMS_SQL包的execute函數來執行語句。
一、使用DBMS_SQL包執行DDL語句
需求:使用DBMS_SQL包根據用戶輸入的表名、字段名及字段類型建表。
create or replace procedure proc_dbms_sql
(
table_name in varchar2 , -- 表名
field_name1 in varchar2 , -- 字段名
datatype1 in varchar2 , -- 字段類型
field_name2 in varchar2 , -- 字段名
datatype2 in varchar2 -- 字段類型
) as
v_cursor number ; -- 定義光標
v_string varchar2 ( 200 ); -- 定義字符串變量
v_row number ; -- 行數
begin
v_cursor: = dbms_sql.open_cursor; -- 爲處理打開光標
v_string: = ' create table ' || ' ' || table_name || ' ( ' || field_name1 || ' ' || datatype1 || ' , ' || field_name2 || ' ' || datatype2 || ' ) ' ;
dbms_sql.parse(v_cursor,v_string,dbms_sql.native); -- 分析語句
v_row: = dbms_sql. execute (v_cursor); -- 執行語句,動態SQL執行DDL時能夠不寫
dbms_sql.close_cursor(v_cursor); -- 關閉光標
exception when others then
dbms_sql.close_cursor(v_cursor); -- 關閉光標
raise;
end ;
以上過程編譯經過後,執行過程建立表結構:
SQL > execute proc_dbms_sql( ' dinya_test2 ' , ' id ' , ' number(8) not null ' , ' name ' , ' varchar2(100) ' );
PL / SQL procedure successfully completed
SQL > desc dinya_test2;
Name Type Nullable Default Comments
-- -- ------------- -------- ------- --------
ID NUMBER ( 8 )
NAME VARCHAR2 ( 100 ) Y
SQL >
二、使用DBMS_SQL包執行DML語句
需求:使用DBMS_SQL包根據用戶輸入的值更新表中相對應的記錄。
查看錶中已有記錄:
SQL > select * from dinya_test2;
ID NAME
1 Oracle
2 CSDN
3 ERP
SQL >
建存儲過程,並編譯經過:
create or replace procedure proc_dbms_sql_update
(
id number ,
name varchar2
) as
v_cursor number ; -- 定義光標
v_string varchar2 ( 200 ); -- 字符串變量
v_row number ; -- 行數
begin
v_cursor: = dbms_sql.open_cursor; -- 爲處理打開光標
v_string: = ' update dinya_test2 a set a.name=:p_name where a.id=:p_id ' ;
dbms_sql.parse(v_cursor,v_string,dbms_sql.native); -- 分析語句
dbms_sql.bind_variable(v_cursor, ' :p_name ' ,name); -- 綁定變量
dbms_sql.bind_variable(v_cursor, ' :p_id ' ,id); -- 綁定變量
v_row: = dbms_sql. execute (v_cursor); -- 執行動態SQL
dbms_sql.close_cursor(v_cursor); -- 關閉光標
exception when others then
dbms_sql.close_cursor(v_cursor); -- 關閉光標
raise;
end ;
執行過程,根據用戶輸入的參數更新表中的數據:
SQL > execute proc_dbms_sql_update( 2 , ' csdn_dinya ' );
PL / SQL procedure successfully completed
SQL > select * from dinya_test2;
ID NAME
1 Oracle
2 csdn_dinya
3 ERP
SQL >
執行過程後將第二條的name字段的數據更新爲新值csdn_dinya。這樣就完成了使用dbms_sql包來執行DML語句的功能。
使用DBMS_SQL中,若是要執行的動態語句不是查詢語句,使用DBMS_SQL.Execute或DBMS_SQL.Variable_Value來執行,若是要執行動態語句是查詢語句,則要使用DBMS_SQL.define_column定義輸出變量,而後使用DBMS_SQL.Execute, DBMS_SQL.Fetch_Rows, DBMS_SQL.Column_Value及DBMS_SQL.Variable_Value來執行查詢並獲得結果。
總結說明: