程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> PL/SQL開發中動態SQL的使用方法

PL/SQL開發中動態SQL的使用方法

編輯:關於SqlServer
內容摘要:在PL/SQL開發過程中,使用SQL,PL/SQL可以實現大部份的需求,但是在某些特殊的情況下,在PL/SQL中使用標准的SQL語句或DML語句不能實現自己的需求,比如需要動態建表或某個不確定的操作需要動態執行。這就需要使用動態SQL來實現。本文通過幾個實例來詳細的講解動態SQL的使用。  

  本文適宜讀者范圍:Oracle初級,中級

  系統環境:

   
OSWindows 2000 Professional (英文版)

   Oracle:8.1.7.1.0

  正文:

  
一般的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中動態SQL可以通過本地動態SQL來執行,也可以通過DBMS_SQL包來執行。下面就這兩種情況分別進行說明:

  一、本地動態SQL

  本地動態SQL是使用EXECUTE IMMEDIATE語句來實現的。

  1、本地動態SQL執行DDL語句:

  需求:根據用戶輸入的表名及字段名等參數動態建表。

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語句。

  2、本地動態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 into v_count using p_id;
end ;

  更多的關於動態SQL中關於返回值及為輸出輸入綁定變量執行參數模式的問題,請讀者自行做測試。

  二、使用DBMS_SQL


  使用DBMS_SQL包實現動態SQL的步驟如下:A、先將要執行的SQL語句或一個語句塊放到一個字符串變量中。B、使用DBMS_SQL包的parse過程來分析該字符串。C、使用DBMS_SQL包的bind_variable過程來綁定變量。D、使用DBMS_SQL包的execute函數來執行語句。

  1、使用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); --執行語句
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>

  2、使用DBMS_SQL包執行DML
語句

  需求:使用DBMS_SQL包根據用戶輸入的值更新表中相對應的記錄。

  查看表中已有記錄:

SQL> select * from dinya_test2;
ID
NAME
1 Oracle
2 CSDN
3 ERP
SQL>

  建存儲過程,並編譯通過:

create or replace

NG>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來執行查詢並得到結果。

  總結說明:

  在Oracle開發過程中,我們可以使用動態SQL來執行DDL語句、DML語句、事務控制語句及系統控制語句。

但是需要注意的是,PL/SQL塊中使用動態SQL執行DDL語句的時候與別的不同,在DDL中使用綁定變量是非法的(bind_variable(v_cursor,’:p_name’,name)),分析後不需要執行DBMS_SQL.Bind_Variable,直接將輸入的變量加到字符串中即可。另外,DDL是在調用DBMS_SQL.PARSE時執行的,所以DBMS_SQL.EXECUTE也可以不用,即在上例中的v_row:=dbms_sql.execute(v_cursor)部分可以不要。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved