1. 程式人生 > >PL/SQL-4 動態SQL

PL/SQL-4 動態SQL

 

---------------------------------------------------------------------------------------
***************************************************************************************
第四部分:動態SQL
***************************************************************************************
---------------------------------------------------------------------------------------
/*
1.什麼是動態SQL?
動態SQL是指在執行PL/SQL塊時動態輸入SQL語句。在PL/SQL塊中只能執行DDL(create、alter、drop)、DCL
(grant、revoke)或比較靈活的SQL語句(如select子句不帶where條件);
動態SQL的效能不如靜態SQL,但是比較靈活;
在PL/SQL塊中編寫動態SQL語句時需要將SQL語句存放到字串變數中而且SQL語句可以包含佔位符(以冒號開始);


2.動態SQL的語法
2.1 使用execute immediate語句
可以處理多數動態SQL操作如:DDL語句(create、alter、drop)、DML語句(insert、update、delete)、DCL(grant、revoke)
以及單行的select子句;但是不能處理多行查詢語句。


2.2 使用open...for,fetch和close語句

在遊標中使用。


2.3 使用批量動態SQL語句

*/

---------------------------------------------------------------
***************************************************************
1. 使用execute immediate

---------------------------------------------------------------
1.1 使用execute immediate處理DDL語句
---------------------------------------------------------------


--案例01:使用execute immediate處理DDL語句--create

declare
create_table  varchar2(200);
begin
create_table:='create table ' ||'&table_name' ||'(sid int, sno int)';
execute  immediate create_table  ;
end;


--案例02:使用execute immediate處理DDL語句---alter

declare
alter_table  varchar2(200);
begin
alter_table:='alter table &target_table_name modify &column_name varchar2(10)';
execute  immediate alter_table  ;
end;

--案例03:使用execute immediate處理DDL語句---drop


declare
drop_table  varchar2(200);
begin
drop_table:='drop table ' ||'&target_table_name';
execute  immediate drop_table  ;
end;

--案例04:使用execute immediate處理DDL語句--drop table

create or replace procedure drop_table (table_name varchar2)
is
sql_sta varchar2(200);
begin
sql_sta:='drop table ' ||table_name;
execute immediate sql_sta;
end;


--呼叫方法:
exec drop_table('accp');

--案例05:使用execute immediate處理DDL語句--create+select
declare
select_sta varchar2(200);
emp_rec emp%rowtype;
begin
execute immediate
'create table sodi(sid int, sno int)';
select_sta:='select * from emp where empno=:id';
execute  immediate select_sta  into emp_rec using &1;   /*使用佔位符時,這個佔位符是在引號內使用的*/
end;


---------------------------------------------------------
1.2 使用execute immediate處理DCL語句
----------------------------------------------------------

--案例01:使用execute immediate處理DCL語句--grant

create or replace procedure grant_priv(priv varchar2, username varchar2)
is
priv_stat varchar2(200);
begin
priv_stat:=' grant '|| priv || ' to ' || username; --注意字串和連線符之間的空格
execute immediate priv_stat;
end;

--呼叫方法
 exec grant_priv('create session', 'scott');

--案例02:使用execute immediate處理DCL語句--revoke

create or replace procedure revoke_priv(priv varchar2, username varchar2)
is
priv_stat varchar2(200);
begin
priv_stat:=' revoke '|| priv || ' from ' || username; --注意字串和連線符之間的空格
execute immediate priv_stat;
end;

--呼叫方法
 exec revoke_priv('create session', 'scott');


----------------------------------------------------------------
1.3.使用execute immediate處理DML語句
----------------------------------------------------------------

1.處理無佔位符和return子句的DML語句

--案例01:查詢子句:select

declare
sql_stat varchar2(100);
begin
sql_stat:='select * from emp';
execute immediate sql_stat;
end;


--案例02:處理無佔位符和return子句的DML語句--insert
declare
insert_table varchar2(200);
begin
insert_table:='insert into &table_name values (&sid, &sno)';
execute immediate insert_table;
end;


--案例03:處理無佔位符和return子句的DML語句--update
declare
update_table varchar2(200);
begin
update_table:='update &table_name set &column_name=&new_value ';
execute immediate update_table;
end;

--案例06:處理無佔位符和return子句的DML語句--delete
declare
delete_table varchar2(200);
begin
delete_table:='delete from  &table_name  ';
execute immediate delete_table;
end;


--案例05:新建一個表然後插入資料--create+insert

declare
create_table  varchar2(200);
begin
create_table:='create table &table_name(sid int, sno int)';
execute  immediate create_table  ;
end;


declare
insert_table varchar2(200);
begin
insert_table:='insert into &table_name values (&sid, &sno)';
execute immediate insert_table;
end;


--案例06:同時實現新建一個表並插入資料--create+insert

declare
create_table  varchar2(200);
insert_table varchar2(200);
begin
create_table:='create table &table_name (sid int, sno int)';
execute  immediate create_table  ;
insert_table:='insert into &table_name values (&sid, &sno)';
execute immediate insert_table;
end;


--案例07:同時實現新建一個表並插入資料--create+insert+update
/*
這裡也可以分開寫

*/


declare
create_table  varchar2(200);
insert_table varchar2(200);
update_table varchar2(200);
begin
create_table:='create table &table_name (sid int, sno int)';
execute  immediate create_table  ;
insert_table:='insert into &table_name values (&sid, &sno)';
execute immediate insert_table;
update_table:='update &table_name set &column_name=&new_value where sid=&old_value';
execute immediate update_table;
end;


--案例08:同時實現新建一個表並插入資料--create+insert+update+delete
declare
create_table  varchar2(200);
insert_table varchar2(200);
update_table varchar2(200);
delete_table varchar2(200);
begin
create_table:='create table &table_name (sid int, sno int)';
execute  immediate create_table  ;
insert_table:='insert into &table_name values (&sid, &sno)';
execute immediate insert_table;
update_table:='update &table_name set &column_name=&new_value where sid=&old_value';
execute immediate update_table;
delete_table:='delete from &delete_tablename';
execute immediate delete_table;
end;


--案例08:同時實現新建一個表並插入資料--create+insert+update+delete+insert
declare
create_table  varchar2(200);
insert_table varchar2(200);
update_table varchar2(200);
delete_table varchar2(200);
re_insert_table varchar2(200);
begin
create_table:='create table &table_name (sid int, sno int)';
execute  immediate create_table  ;
insert_table:='insert into &table_name values (&sid, &sno)';
execute immediate insert_table;
update_table:='update &table_name set &column_name=&new_value where sid=&old_value';
execute immediate update_table;
delete_table:='delete from &delete_tablename';
execute immediate delete_table;
re_insert_table:='insert into &re_table_name values (&new_sid, &new_sno)';
execute immediate re_insert_table;
end;


2.處理佔位符的DML語句


--案例01:處理佔位符的DML語句:create+insert
declare
create_table  varchar2(200);
insert_table varchar2(200);
begin
create_table:='create table &table_name (sid int, sno int)';
execute  immediate create_table  ;
insert_table:='insert into &target_table_name values (:sid, :sno)';
execute immediate insert_table using  &2,&3;
end;


--案例02:處理佔位符的DML語句:create+insert_update
declare
create_table  varchar2(200);
insert_table varchar2(200);
update_table varchar2(200);
begin
create_table:='create table &table_name (sid int, sno int)';
execute  immediate create_table  ;
insert_table:='insert into &target_table_name values (:sid, :sno)';
execute immediate insert_table using  &1,&2;
update_table:='update &update_tablename set &update_column_name=:new_value where &condition_column=:old_value ';
execute immediate update_table using &3 ,&4;
end;


---or
declare
create_table  varchar2(200);
insert_table varchar2(200);
update_table varchar2(200);
begin
create_table:='create table &新建的表名 (sid int, sno int)';
execute  immediate create_table  ;
insert_table:='insert into &插入資料的表名 values (:sid, :sno)';
execute immediate insert_table using  &sid的值 ,&sno的值;
update_table:='update &被更新的表名 set &更新的列名=:new_value where &條件列=:old_value ';
execute immediate update_table using &新值 ,&條件列的值;
end;


--案例03:處理佔位符的DML語句:create+update+insert+delete

declare
create_table  varchar2(200);
insert_table varchar2(200);
update_table varchar2(200);
delete_table varchar2(200);
begin
create_table:='create table &table_name (sid int, sno int)';
execute  immediate create_table  ;

insert_table:='insert into &target_table_name values (:sid, :sno)';
execute immediate insert_table using  &1,&2;

update_table:='update &update_tablename set &update_column_name=:new_value where &update_condition_column=:delete_condition_column_value ';
execute immediate update_table using &3 ,&4;

delete_table:='delete from &dele_table_name where &delete_condition_column=:delete_condition_column_value';
execute immediate delete_table using &5;
end;

---執行過程:
SQL> declare
  2  create_table  varchar2(200);
  3  insert_table varchar2(200);
  4  update_table varchar2(200);
  5  delete_table varchar2(200);
  6  begin
  7  create_table:='create table &table_name (sid int, sno int)';
  8  execute  immediate create_table  ;
  9
 10  insert_table:='insert into &target_table_name values (:sid, :sno)';
 11  execute immediate insert_table using  &1,&2;
 12
 13  update_table:='update &update_tablename set &update_column_name=:new_value
where &update_condition_column=:delete_condition_column_value ';
 14  execute immediate update_table using &3 ,&4;
 15
 16  delete_table:='delete from &dele_table_name where &delete_condition_column=
:delete_condition_column_value';
 17  execute immediate delete_table using &5;
 18  end;
 19  /
輸入 table_name 的值:  sz
原值    7: create_table:='create table &table_name (sid int, sno int)';
新值    7: create_table:='create table sz (sid int, sno int)';
輸入 target_table_name 的值:  sz
原值   10: insert_table:='insert into &target_table_name values (:sid, :sno)';
新值   10: insert_table:='insert into sz values (:sid, :sno)';
輸入 1 的值:  101
輸入 2 的值:  201
原值   11: execute immediate insert_table using  &1,&2;
新值   11: execute immediate insert_table using  101,201;
輸入 update_tablename 的值:  sz
輸入 update_column_name 的值:  sid
輸入 update_condition_column 的值:  sno
原值   13: update_table:='update &update_tablename set &update_column_name=:new_
value where &update_condition_column=:delete_condition_column_value ';
新值   13: update_table:='update sz set sid=:new_value where sno=:delete_conditi
on_column_value ';
輸入 3 的值:  1001
輸入 4 的值:  201
原值   14: execute immediate update_table using &3 ,&4;
新值   14: execute immediate update_table using 1001 ,201;
輸入 dele_table_name 的值:  sz
輸入 delete_condition_column 的值:  sno
原值   16: delete_table:='delete from &dele_table_name where &delete_condition_c
olumn=:delete_condition_column_value';
新值   16: delete_table:='delete from sz where sno=:delete_condition_column_valu
e';
輸入 5 的值:  201
原值   17: execute immediate delete_table using &5;
新值   17: execute immediate delete_table using 201;

PL/SQL 過程已成功完成。

SQL> select * from sz;

未選定行


3.處理包含returning子句的DML語句

--案例01:處理包含returning子句的DML語句--create+insert+update
declare
create_table varchar2(200);
insert_table varchar2(200);
update_table varchar2(200);
res varchar2(100);
begin
create_table:='create table &new_table_name (sid int, sno int)';
execute immediate create_table;
insert_table:='insert into &insert_target_table_name values (:sid, :sno)';
execute immediate insert_table using &1,&2 ;
update_table:='update &update_target_table_name set &udpate_column_name=:new_value where &condition_column_name=:old_value  returning &returning_name into :res';
execute immediate update_table using &3,&4
returning into res;
dbms_output.put_line('the result is : ' ||res);
end;