1. 程式人生 > >Oracle_PL/SQL(2) 過程控制

Oracle_PL/SQL(2) 過程控制

values ber 特定 count varchar 情況 any 包括 except

0.檢索單行數據
0.1使用標量變量接受數據
例1: 7788
declare
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
select ename,sal into v_ename,v_sal from emp where empno=&no;
dbms_output.put_line(‘職員號:‘||&no||‘ 職員名:‘||v_ename);
end;

0.2嵌入SELECT語句註意事項:
使用SELECT INTO語句時,必須要返回一條數據,並且只能返回一條數據
no_date_found:
select into沒有返回數據

too_many_rows:
select into返回多條數據
例2:
declare
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
select ename,sal into v_ename,v_sal from emp where deptno=&deptno;
dbms_output.put_line(‘部門編號:‘||&deptno||‘ 職員名:‘||v_ename);
end;
where子句使用註意事項:
使用的變量名不能與列名相同,否則觸發TOO_MANY_ROWS例外.
例3:
declare
v_ename emp.ename%type;
v_sal emp.sal%type;
empno emp.empno%type;
begin
empno:=&no;
select ename,sal into v_ename,v_sal from emp where empno=empno;
dbms_output.put_line(‘職員編號:‘||&no||‘ 職員名:‘||v_ename);
end;


PL/SQL控制結構
1.按順序執行語句
declare
v_sal number;
v_avg number;
begin
select avg(sal) into v_avg from emp;

dbms_output.put_line(‘平均工資:‘||v_avg);
select sal into v_sal from emp where empno=7788;
dbms_output.put_line(‘職員號7788人員的工資:‘||v_sal);
end;

2.條件分支語句
2.1簡單條件判斷
語法1:
if 邏輯表達式1 then
語句1;
end if;
例1:
declare
v_sal number;
v_avg number;
begin
select avg(sal) into v_avg from emp;
select sal into v_sal from emp where empno=7788;
if v_sal>v_avg then
dbms_output.put_line(‘職員號7788人員的工資‘||v_sal||‘大於平均工資‘||v_avg);
end if;
end;
例2:接收參數
declare
v_sal number(6,2);
begin
select sal into v_sal from emp where lower(ename)=lower(‘&name‘);
dbms_output.put_line(‘輸入的員工姓名是:‘||‘&name‘);
if v_sal<2000 then
update emp set sal=v_sal+200 where lower(ename)=lower(‘&name‘);
dbms_output.put_line(‘給員工:‘||‘&name‘||‘工資增加了200.‘);
end if;
end;

2.2二重條件分支
語法2:
if 邏輯表達式1 then
語句1;
else
語句2;
end if;
例1:
declare
v_sal number;
v_avg number;
begin
select avg(sal) into v_avg from emp;
select sal into v_sal from emp where empno=7788;
if v_sal>v_avg then
dbms_output.put_line(‘職員號7788人員的工資‘||v_sal
||‘大於平均工資‘||v_avg);
else
dbms_output.put_line(‘職員號7788人員的工資‘||v_sal
||‘小於等於平均工資‘||v_avg);
end if;
end;
例2:接收參數 7788
declare
v_comm number(6,2);
begin
select comm into v_comm from emp where empno=&no;
dbms_output.put_line(‘輸入的員工編號是:‘||‘&no‘);
if v_comm is null then
update emp set comm=200 where empno=&no;
dbms_output.put_line(‘給員工編號是:‘||‘&no‘||‘的發200獎金.‘);
else
update emp set comm=comm+100 where empno=&no;
dbms_output.put_line(‘給員工編號是:‘||‘&no‘||‘獎金增加了100.‘);
end if;
end;

2.3多重條件分支
語法3:
if 邏輯表達式1 then
語句1;
elsif 邏輯表達式2 then
語句2
...
else
語句3;
end if;
例1:
declare
v_sal number;
v_avg number;
begin
select avg(sal) into v_avg from emp;
select sal into v_sal from emp where empno=7788;
if v_sal>v_avg then
dbms_output.put_line(‘職員號7788人員的工資‘||v_sal
||‘大於平均工資‘||v_avg);
elsif v_sal<v_avg then
dbms_output.put_line(‘職員號7788人員的工資‘||v_sal
||‘小於平均工資‘||v_avg);
else
dbms_output.put_line(‘職員號7788人員的工資‘||v_sal
||‘等於平均工資‘||v_avg);
end if;
end;

例2:接收參數 7788
declare
v_empno number;
v_job emp.job%type;
begin
v_empno:=&no;
select lower(job) into v_job from emp where empno=v_empno;
dbms_output.put_line(‘輸入的員工編號是:‘||‘&no‘);
if v_job=‘manager‘ then
update emp set comm=nvl(comm,0)+200 where empno=v_empno;
dbms_output.put_line(‘按照員工的職位‘||v_job||‘給員工編號是:‘
||v_empno||‘獎金增加了200.‘);
elsif v_job=‘analyst‘ then
update emp set comm=nvl(comm,0)+100 where empno=v_empno;
dbms_output.put_line(‘按照員工的職位‘||v_job||‘給員工編號是:‘
||v_empno||‘獎金增加了100.‘);
else
update emp set comm=nvl(comm,0)+50 where empno=v_empno;
dbms_output.put_line(‘按照員工的職位‘||v_job||‘給員工編號是:‘
||v_empno||‘獎金增加了50.‘);
end if;
end;

2.4 CASE語句:
在CASE語句中使用單一選擇符進行等值比較
語法1:
case 表達式
when 表達式1 then 語句1; --表達式與表達式1相等時執行語句1
when 表達式2 then 語句2; --同上
...
else
默認語句; --表達式與上述各表達式都不相等時執行默認語句
end case;
例1:
declare
v_deptno emp.deptno%type;
begin
v_deptno:=&no;
dbms_output.put_line(‘輸入的部門編號是:‘||v_deptno);
case v_deptno
when 10 then
update emp set comm=100 where deptno=v_deptno;
dbms_output.put_line(‘給部門編號‘||v_deptno||‘的職員是發100元獎金‘);
when 20 then
update emp set comm=80 where deptno=v_deptno;
dbms_output.put_line(‘給部門編號‘||v_deptno||‘的職員是發80元獎金‘);
when 30 then
update emp set comm=50 where deptno=v_deptno;
dbms_output.put_line(‘給部門編號‘||v_deptno||‘的職員是發50元獎金‘);
else
dbms_output.put_line(‘部門編號不存在‘);
end case;
end;

2.5 在CASE語句中使用多種條件比較
語法2:
case
when 邏輯表達式1 then 語句1; --邏輯表達式1為真時執行語句1
when 邏輯表達式2 then 語句2; --同上
...
else
默認語句; --上述各邏輯表達式都不為真時執行默認語句
end case;

例2:
declare
v_empno emp.empno%type;
v_sal emp.sal%type;
begin
v_empno:=&no;
dbms_output.put_line(‘輸入的職員編號是:‘||v_empno);
select sal into v_sal from emp where empno=v_empno;
case
when v_sal<1000 then
update emp set comm=100 where empno=v_empno;
dbms_output.put_line(‘給工資‘||v_sal||‘小於1000的職員發100元獎金‘);
when v_sal<2000 then
update emp set comm=80 where empno=v_empno;
dbms_output.put_line(‘給工資‘||v_sal||‘小於2000的職員發80元獎金‘);
when v_sal<3000 then
update emp set comm=50 where empno=v_empno;
dbms_output.put_line(‘給工資‘||v_sal||‘小於3000的職員發50元獎金‘);
else
dbms_output.put_line(‘給工資大於等於3000的職員不發獎金‘);
end case;
end;


3.循環語句
分類:loop循環,while循環,for循環
create table temp_table (
num_col number(8),
char_col varchar2(200)
);

3.1 loop循環
語法:
loop
語句;
end loop;
loop循環沒有退出條件,語句被無限次地執行。
一定要包含EXIT語句,定義循環控制變量,並在循環體內改變循環控制變量的值。
循環退出exit
exit when 條件;
if 條件 then
exit;
end if;

declare
v_counter number:=1;
begin
loop
insert into temp_table values (v_counter,‘loop循環‘);
v_counter:=v_counter+1;
if v_counter>=10 then
exit;
end if;
--exit when v_counter>50;
end loop;
end;

3.2 while循環
語法:
while 條件 loop
語句;
end loop;

每次循環前對條件進行判斷,條件為真則語句被執行;否則循環終止。
declare
v_counter number:=1;
begin
while v_counter<=50 loop
insert into temp_table values (v_counter,‘while循環‘);
v_counter:=v_counter+1;
end loop;
end;

while中仍可以使用exit退出循環。
declare
v_counter number:=1;
begin
while v_counter<=50 loop
insert into temp_table values (v_counter,‘while循環exit‘);
v_counter:=v_counter+1;
exit when v_counter>20;
end loop;
end;

3.3 數字式FOR循環
使用FOR循環時,ORACLE會隱含定義循環控制變量.
語法:
for counter in[reverse] lower_bound..upper_bound loop
statement1;
statement2;
.......
end loop;
counter是循環控制變量,並且該變量由ORACLE隱含定義,不需要顯示定義;
lower_bound和upper_bound分別對應循環控制變量的上下界值.
默認情況下,FOR循環,每次會自動增一,指定REVERSE選項時,每次循環控制變量會減一
例1:
begin
for v_counter in 1..10 loop
insert into temp_table values (v_counter,‘for循環‘);
end loop;
end;
例2:reverse 從大向小循環
begin
for v_counter in reverse 1..10 loop
insert into temp_table values (v_counter,‘for循環reverse‘);
end loop;
end;

3.4 隱式遊標for循環
begin
for rs in (select * from emp) loop
insert into temp_table values (rs.empno,rs.ename);
end loop;
end;

begin
for rs in (select * from emp where deptno=10 ) loop
if rs.deptno=10 then
update emp set sal=sal*1.1 where empno=rs.empno;
end if;
end loop;
end;

3.5 嵌套循環
例1:2層for循環
declare
result number;
begin
for i in 1..10 loop
for j in 1..10 loop
result:=i*j;
dbms_output.put_line(i||‘ * ‘||j||‘ = ‘||result);
end loop;
end loop;
end;

例2:乘法口訣表
declare
n_result number;
v_result varchar2(2);
begin
for i in 1..9 loop
for j in 1..i loop
n_result:=j*i;
if n_result<10 and j<>1 then
v_result:=n_result||‘ ‘;
else
v_result:=n_result;
end if;
dbms_output.put(j||‘*‘||i||‘=‘||v_result||‘ ‘);
end loop;
dbms_output.put_line(‘‘);
end loop;
end;

4.退出循環
4.1 continue 退出本次循環(10G以上版本)
begin
for v_counter in 1..50 loop
if v_counter>20 and v_counter<=30 then
continue;
else
insert into temp_table values (v_counter,‘for循環continue‘);
end if;
end loop;
end;

4.2 exit 退出本層循環
begin
for v_counter in 1..50 loop
if v_counter>10 then
exit;
else
insert into temp_table values (v_counter,‘for循環exit‘);
end if;
end loop;
end;
嵌套循環和標號:通過在嵌套循環中使用標號,可以區分內層循環和外層循環,
並且可以在內層循環中直接退出外層循環
例3:
declare
n_result number;
begin
<<outer>>
for i in 1..10 loop
<<inter>>
for j in 1..10 loop
n_result:=i*j;
dbms_output.put_line(‘內層循環內輸出:‘||n_result);
-- exit inter when j=8;
-- exit outer when n_result=30;
end loop inter;
dbms_output.put_line(‘內、外層循環間輸出:‘||n_result);
end loop outer;
dbms_output.put_line(‘外層循環外輸出:‘||n_result);
end;

4.3 goto 用於跳轉到特定標號處去執行語句.
declare
i int :=1;
begin
loop
insert into temp_table values(i,‘loop循環+goto‘);
if i=10 then
goto end_loop;
end if;
i:=i+1;
end loop;
<<end_loop>>
dbms_output.put_line(‘循環結束‘);
end;

5.操縱數據
5.1使用VALUES子句插入數據
declare
v_deptno dept.deptno%type;
v_dname dept.dname%type;
begin
v_deptno:=&no;
v_dname:=‘&name‘;
insert into dept (deptno,dname) values(v_deptno,v_dname);
end;

5.2使用子查詢插入數據
--復制表結構,不帶數據
create table employee as select * from emp where 1=2;
--
declare
v_deptno emp.deptno%type:=&no;
begin
insert into employee select * from emp where deptno=v_deptno;
end;

5.3更新數據
使用表達式更新列值
declare
v_deptno dept.deptno%type:=&no;
v_loc dept.loc%type:=‘&loc‘;
begin
update dept set loc=v_loc where deptno=v_deptno;
end;

5.4使用子查詢更新列值 MILLER
declare
v_ename emp.ename%type:=‘&name‘;
begin
update employee set (sal,comm) =
(select sal,comm from emp where ename=v_ename)
where job = (select job from emp where ename=v_ename)
end;

5.5刪除數據
使用變量刪除數據
declare
v_deptno dept.deptno%type:=&no;
begin
delete from dept where deptno=v_deptno;
end;

5.6使用子查詢刪除數據
declare
v_ename emp.ename%type:=‘&name‘;
begin
delete from employee where deptno=
(select deptno from emp where ename=v_ename);
end;

6.事務控制語句
事務控制語句包括commit,rollback以及savepoint等三種語句
例1:
declare
v_sal emp.sal%type:=&salary;
v_ename emp.ename%type:=‘&name‘;
begin
update emp set sal=v_sal where lower(ename)=v_ename;
select sal into v_sal from emp where ename=v_ename;
dbms_output.put_line(v_sal);
commit;
exception
when others then
--dbms_output.put_line(‘發生了運行時異常‘);
--raise_application_error(-20001,‘發生了運行時異常‘);
rollback;
end;

例2:
declare
begin
insert into temp_table values(1,‘事務控制語句‘);
savepoint a1;
insert into temp_table values(2,‘事務控制語句‘);
savepoint a2;
insert into temp_table values(3,‘事務控制語句‘);
savepoint a3;
rollback to a2;
commit;
end;

Oracle_PL/SQL(2) 過程控制