Oracle 動態SQL

Oracle 動態SQL


一、動態SQL的簡介
1、定義
靜態SQL是指直接嵌入到PL/SQL塊中的SQL語句。
動態SQL是指運行PL/SQL塊是動態輸入的SQL語句。


2、適用範圍
如果在PL/SQL塊中需要執行DDL語句(create,alter,drop等)、DCL語句(grant,revoke等)或更加靈活的SQL語句,需要用到動態SQL。


3、靜態與動態SQL的比較
1)、靜態SQL是在編寫PL/SQL塊是直接嵌入的SQL語句,而動態SQL是在運行PL/SQL塊時動態數據的SQL語句。
2)、靜態SQL性能優於動態SQL。


4、動態SQL的處理方法
1)、適用execute immediate
execute immediate可以處理多數動態SQL操作,包括DDL語句、DCL語句、DML語句、及單行select語句(不能處理多行查詢)。
2)、適用open-for,fetch和colse語句
爲了處理動態的多行查詢操作,必須要使用open-for打開遊標,使用fetch循環提取數據,最終使用close關閉遊標。
3)、使用批量動態SQL
9i新增,通過使用批量動態SQL,可以加快SQL語句處理,進而提高PL/SQL程序的性能。




二、處理非查詢語句及單行查詢語句


1、定義
處理非查詢語句(DDL\DCL\DML等)及單行查詢語句使用execute immediate
語法:
execute immediate dynamic_string
[into [define_name1 [,define_name2]...]
[using [in|out|in out] bind_name1 [,[in|out|in out] bingd_nane2]...]
[[returning|return] into bind_name1[,bind_name2]...];


其中dynamic_string用於指定存放SQL語句或PL/SQL塊的字符串變量;
define用於指定存放單位查詢結果的變量;
bind_name(in)用於指定存放被傳遞給動態SQL值得變量;
bind_name(out)用於指定存放動態SQL返回值得變量;


2、處理DDL操作
create or replace procedure drop_table(table varchar2) is
  v_sql varchar2(100);
begin
  v_sql:='drop table '|| table_name;
  execute immediate v_sql;
end;


3、處理DCL操作
create or replace procudure grant_sys_priv(priv varchar2,username varchar2) is
  v_sql varchar2(100);
begin
  v_sql:='grant '||priv||' to '||username;
  execute immediate v_sql;
end;


4、處理DML操作


1)、處理無佔位符合和returning子句的DML語句
declate
  v_sql varchar2(100);
begin
  v_sql:='update emp set sql=sql*1.1 where deptno=30';
  execute immediate v_sql;
end;


2)、處理包含佔位符的DML語句
declate
  v_sql varchar2(100);
begin
  v_sql:='update emp set sql=sql*(1+:percent/100) where deptno=:dno';
  execute immediate v_sql using &1,&2;
end;


3)、處理包含returning子句的DML語句
說明:使用execute immediate處理帶有returning子句的DML語句時,只能處理作用在單行上的DML語句;
如果DML語句作用在多行上,則必須使用bulk子句,此種情況下之後講述。
declare
  salary number(6,2);
  v_sal varchar2(100);
begin
  v_sql:='update emp set sal=sal*(1+:percent/100) where empno=:eno returning sal into :salary';
  execute immediate v_sql using &1,&2 returning into salary;
  dbms_output.put_line('新工資:'||salary);
end;


5、處理單行查詢
說明:execute immediate不能處理多行查詢。
declare
  v_sql varchar2(100);
  wmp_record emp%rowtype;
begin
  v_sql:='select * from emp where empno=:eno';
  execute immediate v_sql into wmp_record using &1;
  dbms_output.put_line('僱員'||emp_record.ename||'的工資'||emp_record.sal);
end;




三、處理多行查詢語句
說明:需要通過遊標來完成
declare
  type empcurtyp is ref cursor;
  emp_cv empcurtyp;
  emp_record emp%rowtype;
  v_sal varchar2(100);
begin
  v_sql:='select * from emp where deptno=:dno';
  open emp_cv for v_sql using &dno;
  loop
    fetch emp_cv into emp_record;
    exit when emp_cv%notfound;
    dbms_output.put_line('僱員名:'||emp_record.ename||'工資:'||emp.record.sal);
  end loop;
  close emp_cv;
wnd;




四、在動態SQL中使用bulk子句


1、概述
在動態SQL中使用BULK子句爲9i新增特徵,BULK子句實際是動態SQL語句將變量綁定爲集合元素,
集合類型可以是PL/SQL所支持的索引表、嵌套表和VARRAY。但集合元素必須使用SQL數據類型
(例如number、char等),而不能使用PL/SQL數據類型(例binary_integer、boolean等)。


9i開始有三種語句支持BULK子句,execute immediate、fetch和forall,下面逐一講述。


2、在execute immediate語句中使用bulk子句


1)、概述
通過在execute immediate語句中使用bulk子句可以處理作用在多行上的動態DML返回子句,和多行查詢語句。


2)、語法
execute immediate dynamic_name
[bulk collect into define_name[,define_name...]]
[using bind_name[,bind_name...]]
[{returning|return} bulk collect into return_name[,return_name...]];
其中dynamic_name用於指定存放動態SQL語句的字符串變量;
define_name用於指定存放查詢結果的集合變量;
bind_name指定綁定變量(存放傳遞給動態SQL的數據);
return_name指定接收returning子句返回結果的集合變量;


3)、處理作用在多行上的動態DML語句返回子句
declare
  type ename_table_type is table of emp.ename%type index by binary_integer;
  type sal_table_type is table of emp.sal%type index by binary_integer;
  ename_table ename_table_type;
  sal_table sal_table_type;
  v_sql varchar2(100);
begin
  v_sql:='update emp set sal=sal*(1+:percent/100) where deptno=:dno returning ename,sal into :name,:salary';
  execute immediate v_sql using &percent,&dno returning bulk collect into ename_table,sal_table;
  for i in 1..ename_table.count loop
    dbms_output.put_line('僱員'||ename_table(i)||'的新工資爲'||sal_table(i));
  end loop;
end;


4)、處理多行查詢語句
declare
  type ename_table_type is table of emp.ename%type index by binary_integer;
  ename_table ename_table_type;
  v_sal varchar2(100);
begin
  v_sal:='select ename from emp where deptno=:dno';
  execute immediate v_sql bulk collect into ename_table using &dno;
  for i in 1..ename_table.count loop
    dbms_output.put_line(ename_table(i));
  end loop;
end;


3、在fetch語句中使用bulk子句。


1)、概述
在原來的open-for,fetch,close語句處理動態多行查詢語句時,默認每次提取單行數據,循環提取。
通過在fetch語句中引入bulk子句,可以一次提取所有數據。


2)、語法
fetch dynamic_cursor
bulk collect into define_name[,define_name...];


3)、處理多行查詢語句
declare
  type empcurtyp is ref cursor;
  emp_cv empcurtyp;
  type ename_table_type is table of emp.ename%type index by binary_integer;
  ename_table ename_table_type;
  v_sql varchar2(100);
begin
  v_sql:='select ename from emp where job=:title';
  open emp_cv for v_sql using '&job';
  fetch emp_cv bulk collect into ename_table;
  for i in 1..ename_table.count loop
    dbms_output.put_line(ename_table(i));
  end loop;
  close emp_cv;
end;


4、在forall語句中使用bulk子句。


1)、概述
使用forall語句,可允許在動態SQL語句中爲輸入變量同時提供多個數據,
但forall語句只適用於動態的insert\update\delete語句,
不適用於動態select語句,並且forall語句是和execute immediate結合使用的。


2)、語法
forall index in lower bound...upper bound
execute immediate dynamic_name
using bind_name | bind_name(index) [,bind_name | bind_name(index)]...
[{returning | return} bulk collect into bind_name[,bind_name...]];


3)、處理作用在多行上的動態DML語句返回子句
declare
  type ename_table_type is table of emp.ename%type;
  type sal_table_type is table of emp.sal%type;
  ename_table ename_table_type;
  sal_table sal_table_type;
  v_sal varchar2(100);
begin
  ename_table:=ename_table_type('scott','smith','clark');
  v_sql:='update emp set sal=sal*1.1 where ename=:1 returning sal into :2';
  forall i in 1..ename_table.count
    execute immediate v_sql using ename_table(i) returning bulk collect into v_sal;
    for j in 1..ename_table.count loop
      dbms_output.put_line('僱員'||ename_table(i)||'新工資爲'||sal_table(j));
    end loop;
end;


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