1. 程式人生 > >Oracle_PL/SQL(8) 動態sql

Oracle_PL/SQL(8) 動態sql

media 語句 edi 工作 字段 open dml語句 ring 一行

動態sql
0.pl/sql塊的限制
不能執行ddl操作(create、drop、alter);
不能執行部分dcl操作(grant、revoke)。

1.語法
動態sql:在執行時才能確定要執行的sql語句。
在pl/sql塊中編寫動態sql語句時,需要將sql語句存放到字符串變量中,
而且sql可以包含占位符。
execute immediate dynamic_string
dynamic_string :是存放要被執行的sql語句的字符串變量。

2.用途
可處理:
ddl語句(create,alter,drop),
dcl語句(grant,revoke),
dml語句(insert,update,delete)

單行select語句
多行select語句需要和遊標聯合使用。

3.ddl操作
execute immediate後面只需要帶有ddl語句
create or replace procedure drop_table(table_name varchar2)
is
sql_statement varchar2(100);
begin
sql_statement:=‘drop table ‘||table_name;
execute immediate sql_statement;
end;
/
exec drop_table(‘emp_log‘);

4.dcl操作(grant、revoke)
conn sys/123 as sysdba;

create or replace procedure grant_sys_priv(priv varchar2,username varchar2)
is
sql_stat varchar2(100);
begin
sql_stat:=‘grant ‘||priv||‘ to ‘||username;
execute immediate sql_stat;
end;
/
--授權前檢查
select * from user_sys_privs;
--授權
exec grant_sys_priv(‘create any table‘,‘scott‘)
--grant create any view,drop any view to scott;

create or replace procedure revoke_sys_priv(priv varchar2,username varchar2)
is
sql_stat varchar2(100);
begin
sql_stat:=‘revoke ‘||priv||‘ from ‘||username;
execute immediate sql_stat;
end;
/

5.dml操作
5.1 sql語句不需要參數
declare
sql_stat varchar2(100);
begin
--update emp set sal=sal*1.1 where deptno=30;
sql_stat:=‘update emp set sal=sal*1.1 where deptno=30‘;
execute immediate sql_stat;
end;

5.2 sql語句需要參數
: 占位符--》綁定變量
using 傳遞參數
& 從客戶端接收參數
declare
sql_stat varchar2(100);
begin
sql_stat:=‘update emp set sal=sal*(1+:percent/100) where deptno=:dno‘;
execute immediate sql_stat using &percent,&dno;
end;
改造:
create or replace procedure proc_emp_addsal(p_dno number,p_percent number)
is
begin
update emp set sal=sal*(1+p_percent/100) where deptno=p_dno;
end;

6.單行select語句
需要使用into子句接受返回數據
語法:
execute immediate dynamic_string
[into (define_variable|record)]
[using bind_argument]

declare
sql_stat varchar2(100);
v_ename emp.ename%type;
begin
sql_stat:=‘select ename from emp where empno=:enp‘;
execute immediate sql_stat into v_ename using &enp;
dbms_output.put_line(‘雇員:‘||v_ename);
end;
改造:
create or replace function func_emp_ename(p_empno number) return varchar2
is
v_ename emp.ename%type;
begin
select ename into v_ename from emp where empno=p_empno;
return v_ename;
end;

7.多行select語句
7.1 使用遊標
為了處理動態的多行查詢操作,必須要使用open-for語句打開遊標,
使用fetch循環提取數據,close關閉遊標
declare
type empcurtyp is ref cursor;
emp_cv empcurtyp;
emp_record emp%rowtype;
sql_stat varchar2(100);
begin
sql_stat:=‘select * from emp where deptno=:dno‘;
open emp_cv for sql_stat 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;
end;

7.2 bulk collect into 集合
bulk collect批量操作
declare
type ename_table_type is table of emp%rowtype;
ename_table ename_table_type;
sql_stat varchar2(100);
begin
sql_stat:=‘select * from emp where deptno=:dno‘;
execute immediate sql_stat bulk collect into ename_table using &dno;
for i in 1..ename_table.count loop
dbms_output.put_line(‘雇員名:‘||ename_table(i).ename||‘,工資:‘||ename_table(i).sal);
end loop;
end;

改造:
create or replace procedure proc_emp_enamesal(p_dno number)
is
begin
for rs in (select * from emp where deptno=p_dno) loop
dbms_output.put_line(‘雇員名:‘||rs.ename||‘,工資:‘||rs.sal);
end loop;
end;
/

exec proc_emp_enamesal(20);

8.實際工作中的用途
8.1 對於分表處理
create or replace procedure proc_stu (p_tab varchar2,p_id number)
is
type ename_table_type is table of stu_oracle%rowtype;
ename_table ename_table_type;
sql_stat varchar2(100);
begin
sql_stat:=‘select * from ‘||p_tab||‘ where id=‘||p_id;
execute immediate sql_stat bulk collect into ename_table;
for i in 1..ename_table.count loop
dbms_output.put_line(‘學生名:‘||ename_table(i).sname);
end loop;
end;
/
show err;

begin
proc_stu(‘stu_java‘,11);
end;

8.2 對拼接函數通用功能的實現
create or replace function func_concat(p_expectfield varchar2,
p_expecttable varchar2,p_expectcause varchar2) return varchar2
is
/*
函數功能:獲取單個屬性將其拼成一行
參數說明:p_expectfield 查詢字段
p_expecttable 查詢主表
p_expectcause 查詢條件
*/
v_sql varchar2(4000):=‘‘;
type type_cursor is ref cursor;
v_cur type_cursor;
v_per varchar2(4000):=‘‘;
v_cnt number:=0;
v_return varchar2(4000):=‘‘;
begin
v_sql:=‘select ‘||p_expectfield||‘ from ‘||p_expecttable||‘ where ‘||p_expectcause;
open v_cur for v_sql;
loop
fetch v_cur into v_per;
exit when v_cur%notfound;
if v_cnt=0 then
v_return:=v_per;
else
v_return:=v_return||‘,‘||v_per;
end if;
v_cnt:=v_cnt+1;
end loop;
close v_cur;
return v_return;
end func_concat;
/
show err;

select func_concat(‘ename‘,‘emp‘,‘1=1‘) from dual;
select func_concat(‘distinct job‘,‘emp‘,‘deptno=20‘) from dual;
select func_concat(‘dname‘,‘dept‘,‘1=1‘) from dual;
--select ename from emp,dept where emp.deptno=dept.deptno and dept.deptno=20;
select func_concat(‘ename‘,‘emp,dept‘,‘emp.deptno=dept.deptno and dept.deptno=20‘) from dual;
--select job from emp where ename=‘scott1‘;
select func_concat(‘job‘,‘emp‘,‘ename=‘‘scott1‘‘‘) from dual;
--select ename from emp,dept where emp.deptno=dept.deptno and lower(dname)=‘sales‘;
select func_concat(‘ename‘,‘emp,dept‘,‘emp.deptno=dept.deptno and lower(dname)=‘‘sales‘‘‘) from dual;

作業:
1.用動態sql創建表,給表增加列、刪除列、修改列長度;
2.用動態sql創建表,給表增加主鍵約束、唯一鍵約束、外鍵約束;
3.用動態sql截斷表;
4.用動態sql實現部門表的Insert、Delete功能

Oracle_PL/SQL(8) 動態sql