Oracle中動態SQL詳解


一:靜態SQL與動態SQL
  Oracle編譯PL/SQL程序塊分為兩種:一種為前期聯編(early binding),即SQL語句在程序編譯期間就已經確定,大多數的編譯情況屬於這種類型;另外一種是后期聯編(late binding),即SQL語句只有在運行階段才能建立,例如當查詢條件為用戶輸入時,那么Oracle的SQL引擎就無法在編譯期對該程序語句進行確定,只能在用戶輸入一定的查詢條件后才能提交給SQL引擎進行處理。通常,靜態SQL采用第一種編譯方式,而動態SQL采用后一種編譯方式。
  本文主要討論動態SQL的相關內容。 

二:動態SQL程序開發
  理解了動態SQL編譯的原理,也就掌握了其基本的開發思想。動態SQL既然是一種”不確定”的SQL,那其執行就有其相應的特點。Oracle中提供了Execute immediate語句來執行動態SQL,語法如下:

1 execute immediate 動態SQL語句
2 using 綁定參數列表
對這一語法作如下說明:

1)動態SQL是指DDL和不確定的DML(即帶參數的DML);
2)綁定參數列表為輸入參數列表,即其類型為in類型,在運行時刻與動態SQL語句中的參數(實際上占位符,可以理解為函數里面的形式參數)進行綁定;
3)由於動態SQL是在運行時刻進行確定的,所以相對於靜態而言,其更多的會損失一些系統性能來換取其靈活性。

 

 

 

舉例:設數據庫的emp表,其數據為如下:

ID NAME SALARY
100 Jacky 5600
101 Rose 3000
102 John 4500

 

 

 

1.創建該表、添加數據。 

 1 declare
 2   tablename varchar2(20); --表名
 3   field1    varchar2(20); --字段1名稱
 4   datatype1 varchar2(20); --字段1類型
 5   field2    varchar2(20); --字段2名稱
 6   datatype2 varchar2(20); --字段2類型
 7   field3    varchar2(20); --字段3名稱
 8   datatype3 varchar2(20); --字段3類型
 9   str_sql   varchar2(500); --拼接sql語句的字符串
10 begin
11   tablename := 'emp';
12   field1    := 'id';
13   datatype1 := 'number';
14   field2    := 'name';
15   datatype2 := 'varchar(10)';
16   field3    := 'salary';
17   datatype3 := 'number';
18   str_sql   := 'create table '||tablename||'('||field1||' '||datatype1||','||field2||' '||datatype2||','||field3||' '||datatype3|| ')';
19   execute immediate str_sql;
20 exception
21   when others then
22     dbms_output.put_line('操作失敗!');
23 end;
 1 declare
 2   v_id    number;
 3   v_name  varchar(20);
 4   v_salary number;
 5   str_sql varchar2(500); --保存拼接的sql語句
 6 begin
 7   v_id    := &vid;
 8   v_name  := '&name';
 9   v_salary:= &vsal;
10   
11   str_sql := 'insert into emp values(:1,:2,:3)'; --使用占位符代表變量
12   execute immediate str_sql
13   using v_id, v_name,v_salary; --使用變量替換sql中的占位符,v_id替換:1,v_name替換:2,依此類推。
14   
15   commit;
16 end;

2.根據大於特定的薪水的查詢相應的員工信息。 

 1 create or replace procedure find_emp(p_salary number) is
 2   v_emp emp%rowtype;
 3   type my_cursor is ref cursor; 
 4   v_my_cursor my_cursor;
 5 begin
 6   open v_my_cursor for 'select * from emp where salary >:1'
 7   using p_salary;
 8   
 9   loop
10     fetch v_my_cursor into v_emp;
11     exit when v_my_cursor%notfound;
12     dbms_output.put_line('薪水大於'||p_salary||' 的員工有: ');
13     dbms_output.put_line('id為 '||v_emp.id||' 姓名為:'||v_emp.name);
14   end loop;
15   close v_my_cursor;
16 end;

3.刪除指定表的數據,並通過out類型參數返回影響的行數。

1 create or replace procedure del_rows(p_table_name in varchar2,
2                                      p_rows_deld  out number) is
3 begin
4   execute immediate 'delete from '||p_table_name;
5   p_rows_deld := sql%rowcount;
6 end;

注意第2個程序動態SQL語句使用了占位符“:1“,其實它相當於函數的形式參數,使用”:“作為前綴,然后使用using語句將p_salary在運行時刻將:1給替換掉,這里p_salary相當於函數里的實參。其中打開的游標為動態游標,它也屬於動態SQL的范疇,其整個編譯和開發的過程與execute immediate執行的過程很類似。 

:小結

  本文對動態SQL的編譯原理、開發過程進行簡單介紹,對動態SQL程序開發有了一個總體的認識。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM