動態sql 和靜態sql 下篇

2021-06-27 06:10:19 字數 4715 閱讀 3295

動態sql 和靜態sql 下篇

1、批量繫結讓oracle 在對一組值進行sql操作時繫結乙個變數,這一組資料可以是任何的plsql的聚合型別(聯合陣列,內嵌表,可變陣列),

集合元素必須是sql的資料型別,比如char date mumber。有三個句法支援動態批量繫結,execute immediate , fetch , forall;

execute immediate: 你可以用bulk collect into子句和execute immediate宣告去儲存 乙個查詢集合的每一列到乙個分散的集合中去。

你可以用returning bulk collect into子句和execute immediate去儲存insert ,update或者delete的結果集到乙個集合中。

fetch: 你可以用bulk collect into和fetch子句去儲存游標的每一列值到乙個集合中。

forall: 你可以用execute immediate宣告把returning bulk collect into放在乙個forall裡面.你可以去儲存insert ,update或者delete的結果集到乙個集合中。

2、動態繫結的例子:

動態sql中的bulk collect into 子句:

declare

type empcurtyp is ref cursor;

type numlist is table of number;

type namelist is table of varchar2(25);

emp_cv 

empcurtyp;

empids 

numlist;

empnames namelist;

sals 

numlist;

begin

open emp_cv for ' select employee_id,last_name from employees';

fetch emp_cv bulk collect into empids,enames; 

--批量存入內嵌表empids和enames。

close emp_cv; 

--關閉游標

execute immediate ' select salary from employees' bulk cololect into sals; 

--批量存入sals表。

end;

動態sql中的returning bulk collect into 和 using子句:

declare

type namelist is table of varchar2(15);

enames 

namelist;

bonus_amt number:=50;

sql_stmt varchar2(200);

begin

sql_stmt:='update employees set salary =salary :1 returning last_name into :2';

execude 

immediate sql_stmt

using bonus_amt returning bulk collect into enames; --sql_stmt中用了returning。。。。

end;

動態sql中用forall 和 using子句:

declare

type numberlist is table of number;

type namelist is table of varchar2(15);

empids numlist;

enames namelist;

begin

empids:=numlist(101,102,103,104,105);

forall i in 1..5

execute immediate

'update employees set salary=salaruy *1.04 where employee_id=:1 returning last_name into :2' 

--注意這裡沒有分號結束,這個例子與上面的例子是不同的,這是一句整體的話。

using empids(i) returning bulk collect into enames;

end;

3、提高帶有繫結變數的動態sql的效能

當你在plsql語句中用到 insert ,update,delete,select語句時,plsql把變數自動的轉變成繫結的變數,這樣就能使語句執行的更加迅速,

但是在動態sql中,你需要自己去繫結變數,以達到更好地效能。

下面的例子中,oracle為每個單獨的emp_id開啟了乙個單獨的cursor,這樣帶來的資源競爭和效能低下是可想而知的:

create procedure fire_employee (emp_id 

number) as

begin

execute immediate 'delete from employee where employee_id=' || to_char(emp_id);

end;

當然我們可以用下面的繫結變數的方法,為不同的emp_id重用乙個cursor:

create procedure fire_employee(emp_id) as

begin

execute immediate 'delete from employee where employee_id= :id' using emp_id; 

--這句話就表示繫結了變數。

end;

看下面乙個傳遞物件名作為引數的例子:

create procudure drop_table(table_name in varchar2) as

begin

execute immediate 'drop table' || table_name;

end;

如果你要呼叫乙個不知道名字的過程(當執行時才知道名字):

create procedure run_proc(proc_name in varchar2, table_name in varchar2) as

begin

execute immediate 'call " 

' || proc_name| | ' "( :proc_name) ' using table_name;

end;

下面來呼叫上面的過程:

create table employees_temp as select last_name from employees;

begin

run_proc('drop_table' , 'employees_temp'); 

--傳入兩個實參,乙個是過程引數drop_table過程,另乙個是表employees_temp。

end; 

4、重複佔位符的使用:

在動態sql中,佔位符和變數的繫結是由位置決定的,而不是由名字決定的,有乙個例子很好的說明一下:

sql_stmt :='insert into payroll values(:x,:x,:y,:x)';

在這裡x是沒有實際意義的,它只是佔據了乙個位置,在using子句中你可以繫結四個不同的值:

execute immediate sql_semt using a,a,b,a;

如果乙個動態的宣告代表了乙個plsql塊,那這個規則就不一樣了:每乙個單獨的佔位符在using子句中對應乙個單獨的字元。如果相同的佔位符出現多次,在using子句中和繫結的變數一致的參照的名字相對應:

create procedure calc_stats(w number , x number , z number ) is

begin

dbms_output.put_line(w x y z);

end; /

declare  a 

number:=4; b 

number:=7;

plsql_block varchar2(100); --宣告乙個plsql塊的字串。

begin

plsql_block:='begin calc_stats(:x , :x, :y, :x, ) ; 

end ;'; 

--這是在乙個plsql塊中的佔位符,注意與上面的區分好。

execute immediate plsql_block using a,b; 

--a代表先出現的x,b代表後出現的y。

end;

5、在動態sql中用cursor的屬性(%found, %isopen, %notfount, %rowcount):

declare

type cursor_ref is ref cursor;

c1 cursor_ref;

type emp_tab is table of employees%rowtype;

rec_tab emp_tab;

rows_fetched 

number;

begin

open c1 for 'select * from employees';

fetch c1 bulk collect into rec_tab;

rows_fetched:=c1%rowcount;

dbms_output.put_line('number of employees fetched:' || to_char(rows_fetched));

end;

**:

Oracle動態SQL和靜態SQL比較

oracle動態sql和靜態sql比較 1 靜態sqlsql與動態sql oracle編譯pl sql程式塊分為兩個種 其一為前期聯編 early binding 即sql語句在程式編譯期間就已經確定,大多數的編譯情況屬於這種型別 另外一種是後期聯編 late binding 即sql語句只有在執行...

靜態SQL與動態SQL的比較

靜態sql與動態sql相比具備很多優點,最主要的表現在兩個方面 1 靜態sql指定具體的物件,可以避免動態sql中隱含的錯誤 2 靜態sql的分析和執行速度比動態sql要快 1 尋找消除動態sql的機會 一般而言,想採用動態sql實現的語句中都有不確定的因素,如果所有資訊都確定,沒有理由採用動態sq...

靜態SQL與動態SQL的比較

靜態sql與動態sql相比具備很多優點,最主要的表現在兩個方面 1 靜態sql指定具體的物件,可以避免動態sql中隱含的錯誤 2 靜態sql的分析和執行速度比動態sql要快 1 尋找消除動態sql的機會 一般而言,想採用動態sql實現的語句中都有不確定的因素,如果所有資訊都確定,沒有理由採用動態sq...