oracle的動態sql


動態SQL

(1).區分靜態SQL和動態SQL
(2).用動態SQL處理非查詢語句
(3).使用動態SQL處理多行查詢語句
(4).用集合處理動態SQL語句


1.靜態SQL
靜態SQL指直接嵌入在PL/SQL塊中的SQL語句,靜態SQL用於完成特定或固定的任務。
select sal from emp where empno=4000;


2.動態SQL

動態SQL運行PL/SQL塊時動態輸入的SQL語句。若是在PL/SQL須要執行DDL語句,DCL語句,或則須要執行更加靈活的SQL語句(select中有不一樣where條件),須要用到用到動態SQL。
編寫動態SQL語句時,須要將SQL語句存放到字符串變量中,並且SQL語句能夠包含佔位符(以冒號開始)。
v_sql varchar2(100);
v_sql:='delete from emp where empno =:v_empno';





3.三種不一樣類型的動態SQL方法

(1)使用execute immediate 語句
除不能處理多行查詢語句,其餘的動態SQL包括DDL語句,DCL語句以及單行的SELECT查詢均可以。

(2)ref cursor 動態遊標,使用open-for,fetch,close
能處理動態的多行查詢操做,必需要使用open-for語句打開遊標,使用fetch語句循環提取數據,最終使用close語句關閉遊標。

(3)使用批量bulk collect動態SQL
經過使用批量動態SQL語句,能夠加快SQL語句處理,進而提升PL/SQL的性能。


4.execute immediate語句語法
execute immediate dynamic_string
[into {define_variable[,define_variable...]}]
[using [in|out|in out] bind_argument]
[{return|returning} into bind_argument...]


#######execute immeidate

(1)使用execute immeidate語句處理單行DDL操做

//刪除某個表
create or replace procedure pro_drop_table(v_table_name varchar2)
is
v_sql varchar2(100);
begin

v_sql := 'drop table ' || v_table_name;
execute immediate v_sql;

end;


(2)處理DCL操做
//授予某個權限給某個用戶
create or replace procedure pro_grant_priv(v_priv varchar2,v_username varchar2)
is
v_sql varchar2(100);

begin

v_sql := 'grant ' || v_priv || ' to ' || v_username;
execute immediate v_sql;

end;


//測試
exec pro_grant_priv('create session','test_1')

(3)處理DML操做
若是DML語句中包含佔位符,那麼在execute immediat語句以後必需要帶有using語句。若是DML語句中帶有returning子句,那麼在execute immediate語句以後須要帶有returning into子句

//給不一樣部門增長工資


declare
v_sql varchar2(100);
begin
v_sql := 'update emp set sal = sal*(1+:v_percent/100) where deptno=:v_deptno';
execute immediate v_sql using &1,&2;
end;


################ref cursor 動態遊標的使用
5.使用open..for,fetch..into,close語句

動態處理select語句返回多行數據

(1)定義遊標變量
type cursor_type is ref cursor;
cursor_variable cursor_type;


(2)打開遊標變量
open cursor_variable for dynamic_string
[using bind_argument....];


(3)循環提取數據
fetch cursor_variable into {var1,var2....|record_var};
var指提取表量變量,record_var提取記錄變量。

(4)關閉遊標
close cursor_variable;

//顯示指定部門的全部僱員名和工資
create or replace procedure pro_info(v_deptno number)
is
type emp_cursor_type is ref cursor;
emp_cursor emp_cursor_type;
emp_record emp%rowtype;

v_sql varchar2(100);

begin
v_sql:='select * from emp where deptno=:v_deptno';
open emp_cursor for v_sql using v_deptno;

loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound;
dbms_output.put_line('ename: '|| emp_record.ename ||',salary: ' ||emp_record.sal);

end loop;
close emp_cursor;
end;




##########bulk collect的使用
6.批量動態SQL---bulk


bulk加快批量數據的處理速度,使用bulk子句時,實際是動態SQL語句將變量綁定爲集合元素。
集合元素必須使用SQL數據類型(char,number,varchar2,date,timestamp),不能使用PL/SQL數據類型(binary_integer,boolean)。

動態BULK子句的語法:
execute immediate dynamic_string
[bulk collect into  define_variable...]
[using bind_argument...]
[{returning | return} bulk collect into return_variable...]


//顯示特定部門的全部僱員名


set serveroutput on;
declare
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 deptno=:v_deptno';
execute immediate v_sql bulk collect into ename_table using &v_deptno;
for i in 1..ename_table.count loop
dbms_output.put_line(ename_table(i));
end loop;
end;


做業:
1.動態修改特定部門的工資,並返回修改後的僱員名和工資---scott---emp
//使用遊標
create or replace procedure pro_change_sal(v_deptno emp.deptno%type,v_percent number)
is
type cursor_emp_type is ref cursor;
emp_record emp%rowtype;
emp_cursor cursor_emp_type;
v_sql varchar2(100);
begin
update emp set sal=sal*(1+v_percent/100) where deptno=v_deptno;
v_sql:='select * from emp where deptno=v_deptno';
open emp_cursor for v_sql ;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound ;
dbms_output.put_line('ename: '|| emp_record.ename ||',salary: ' ||emp_record.sal);
end loop;
close emp_cursor;
end;

####################
//批量處理
set serveroutput on;
create or replace  procedure pro_change_sal(v_deptno emp.deptno%type,v_percent number)
is
type sal_table_type is table of emp.sal%type index by binary_integer;
type ename_table_type is table of emp.ename%type index by binary_integer;
ename_table ename_table_type;
sal_table sal_table_type;
v_sql varchar2(100);
begin
update emp set sal=sal*(1+v_percent/100) where deptno=v_deptno;
v_sql:='select ename,sal from emp where deptno=:v_deptno';####必須使用:v_deptno加冒號
execute immediate v_sql bulk collect into ename_table,sal_table using v_deptno;
for i in  1..ename_table.count loop
dbms_output.put_line('ename: '|| ename_table(i) ||',salary: ' ||sal_table(i));
end loop;
end;
2.根據輸入的多個訂單號更新交付日期爲當前日期,並返回每隔訂單的對應的客戶編號.
create or replace procedure pro_change_ship_date(id1 number,id2 number,id3 number)
is
type customer_id_table_type is table of number;
type ordre_id_table_type is table of number;
customer_id_table customer_id_table_type;
ordre_id_table ordre_id_table_type;
v_sql varchar2(100);
begin
update orders set ship_date=sysdate where order_id in (id1 ,id2 ,id3);
v_sql :='select customer_id, order_id from orders where order_id in ( :id1 ,:id2 ,:id3)';
execute immediate v_sql  bulk collect into customer_id_table,ordre_id_table using id1 ,id2 ,id3;
for i in 1.. customer_id_table.count loop
dbms_output.put_line('ordre_id '||ordre_id_table(i)||' '||'customer_id '||customer_id_table(i));
end loop;
end;
sql

相關文章
相關標籤/搜索