第四章異常處理
PL/SQL 塊是構成 PL/SQL 程序的基本單元
將邏輯上相關的聲明和語句組合在一起
PL/SQL 分為三個部分,聲明部分、可執行部分和異常處理部分
[DECLARE declarations] BEGIN executable statements [EXCEPTION handlers] END;
以下示例演示了如何使用PL/SQL 語句:
declare
area integer;
width integer;
height integer;
currentdate date;
cnumber constant integer := 10;
begin
area :=10;
height :=2;
width := area/height;
currentdate :=sysdate;
DBMS_OUTPUT.put_line('寬 = '||width);
DBMS_OUTPUT.put_line('高 ='||height);
DBMS_OUTPUT.put_line('面積 ='||area);
DBMS_OUTPUT.put_line('常量的值為:'||cnumber);
DBMS_OUTPUT.put_line('當前時間為:'||currentdate);
exception
when zero_divide then
DBMS_OUTPUT.put_line('除數不能為零');
end;
給變量賦值有兩種形式:
使用賦值語句 :=
使用 SELECT INTO 語句
使用常量賦值:
cnumber constant integer := 10;
以下代碼演示了使用常量和SELECT INTO 語句:
declare
firstName varchar2(20);
lastName varchar2(20);
employeeid number;
consNumber constant integer :=1000;
begin
select employee_id, first_name,last_name into employeeid, firstName,lastname from employees2 where employee_id =1;
DBMS_OUTPUT.put_line('consNumber = '||consNumber);
DBMS_OUTPUT.put_line('employeeid='||firstName);
DBMS_OUTPUT.put_line('firstName='||firstName);
DBMS_OUTPUT.put_line('lastName='||lastname);
end;
CLOB數據類型的使用。
create table my_book_text( chapter_id number(3), chapter_descr varchar2(40), chapter_text clob);
添加數據到clob字段 chapter_text :
insert into my_book_text values(5,'第五章 PL/SQL 簡介','PL/SQL 可用於創建存儲過程,觸發器和程序包等,用來處理業務規則,數據庫時間或給SQL命令的執行添加程序邏輯。');
讀取 CLOB 數據類型:
set serveroutput on declare clob_var clob; amount integer; offset integer; output_var varchar2(100); begin select chapter_content into clob_var from my_book_text where chapterid=1; amount :=20; offset :=5; DBMS_LOB.READ(clob_var,amount,offset,output_var); DBMS_OUTPUT.put_line(output_var); end; /
PL/SQL 支持的流程控制結構:
條件控制
IF 語句
CASE 語句
循環控制
LOOP 循環
WHILE 循環
FOR 循環
順序控制
GOTO 語句
NULL 語句
以下代碼演示了條件控制(IF-THEN-ELSE語句):
declare
age number(8);
begin
age := &age;
if age>20 and age<30 then
dbms_output.put_line('年齡在20 和30 之間 ');
elsif age < 20 then
dbms_output.put_line('年齡小於20');
else
dbms_output.put_line('年齡大於30');
end if;
end;
/
以下代碼演示了從 employees2 表中檢索employee_id 為 3 的記錄 ,如果 salary 大於 15000 則減去 1000 ,否則salary 加 100
declare
firstName varchar(20);
lastName varchar2(20);
salarytemp number(10);
begin
select first_name,last_name,salary into firstName,lastName,salarytemp from employees2 where employee_id=3;
if salarytemp > 15000 then
update employees2 set salary = salary-1000 where employee_id = 3;
else
update employees2 set salary = salary+100 where employee_id=3;
end if;
dbms_output.put_line('firstName ='||firstName);
dbms_output.put_line('lastName='||lastName);
dbms_output.put_line('salarytemp = '||salarytemp);
end;
Case 語句:
以下代碼演示了選擇器。系統先計算選擇器值。然後再依次選擇 WHEN 子句。
set serveroutput on
begin
case '&grade'
when 'A' then dbms_output.put_line('優異');
when 'B' then dbms_output.put_line('優秀');
when 'C' then dbms_output.put_line('良好');
when 'D' then dbms_output.put_line('一般');
when 'E' then dbms_output.put_line('較差');
else dbms_output.put_line('沒有此成績');
end case;
end;
/
Loop 循環:以下代碼演示了loop的使用
declare
x number;
begin
x :=0;
loop
x:=x+1;
if x>=3 then
exit;
end if;
dbms_output.put_line('循環體 x ='||x);
end loop;
dbms_output.put_line('循環體外 x ='||x);
end;
/
另外一種表現形式:
declare
x number;
begin
x :=0;
loop
x:=x+1;
exit when x>=3;
dbms_output.put_line('循環體內 x ='||x);
end loop;
dbms_output.put_line('循環體外 x ='||x);
end;
While循環:
declare
x number ;
begin
x:=0;
while x<=3 loop
x:=x+1;
dbms_output.put_line('循環內'||x);
end loop;
dbms_output.put_line('循環外'||x);
end;
/
以下代碼演示了while 循環得使用。聲明了銷量的 monthly_value 和 daily_value,並將其初始化為0。While執行循環,直至每月銷量的值大於等於4000
set serveroutput on
declare
monthly_value number :=0;
daily_value number :=0;
begin
while monthly_value <= 4000
loop
monthly_value := daily_value * 31;
daily_value := daily_value +10;
dbms_output.put_line('每日銷量:' || daily_value);
end loop;
dbms_output.put_line('每月銷量' || monthly_value);
end;
/
For循環語句:
begin
for i in 1..5 loop
dbms_output.put_line('循環 I 的值 = '||i);
end loop;
dbms_output.put_line('end loop');
end;
/
Reverse(遞減) 的使用
begin
for i in reverse 1..5 loop
dbms_output.put_line('循環 I 的值 = '||i);
end loop;
dbms_output.put_line('end loop');
end;
/
以下代碼顯示了25個偶數
set serveroutput on begin for eve_number in 1..25 loop dbms_output.put_line(eve_number*2); end loop; end; /
Oracle 中異常的處理:
預定義異常:
返回多行異常:
declare
firstname varchar2(20);
begin
select first_name into firstname from employees2 where division_id ='SAL';
dbms_output.put_line('first_name=' || firstname);
exception
when too_many_rows then
dbms_output.put_line('不能返回多行數據');
end;
/
用戶自定義異常:
以下代碼演示了用戶接受輸入的類別。IF 語句將用戶輸入的類別與指定的類別相匹配。如果指定的類別中不存在將引發typeException 異常
declare
typeException exception;
temptype varchar2(20);
begin
temptype :='&type';
if temptype not in ('java','c++','c#') then
raise typeException;
else
dbms_output.put_line('temptype = '||temptype);
end if;
exception
when typeException then
--dbms_output.put_line('沒有找到相應的類型');
raise_application_error(-20000,'沒有找到相應的類型');
end;
存儲過程的使用:
過程是執行某些操作的子程序,它是執行特定任務的模塊,它可以被賦予參數,存儲在數據庫中。以下代碼
1. 創建存儲過程語法:
CREATE [OR REPLACE] PROCEDURE <procedure name> [(<parameter list>)] IS|AS <local variable declaration> BEGIN <executable statements> [EXCEPTION <exception handlers>] END;
以下代碼演示了如何創建一個不帶參數的存儲過程:
create or replace procedure pro_emp
as
firstName varchar2(20);
lastName varchar2(20);
salary number(20);
begin
select first_name,last_name,salary into firstName,lastName,salary from employees2 where employee_id = 1;
dbms_output.put_line('firstName = '||firstName);
dbms_output.put_line('lastName = ' ||lastName);
dbms_output.put_line('salary = ' ||salary);
exception
when no_data_found then
dbms_output.put_line('數據沒有找到');
end;
執行以上存儲過程:
execute pro_emp ;
過程參數模式:參數傳遞的模式有三種IN , OUT , IN OUT
IN 是參數的默認模式,這種模式定義的參數在程序運行的時候已經具有值,在過程序體中這個值不會改變。
OUT 模式定義的參數只在過程內部賦值。
IN OUT 模式定義的參數當過程運行時可能已經具有值,但是在過程體中也可以修改
以下創建了帶參數的過程:
create or replace procedure mypro(employeeid in number,divisionid in out va rchar2,jobid out varchar2) as tempdivid varchar2(20); tempjobid varchar2(20); begin select division_id,job_id into tempdivid,tempjobid from employees2 where employee_id =employeeid; divisionid :=tempdivid; jobid :=tempjobid; end;
執行以上過程:
declare
cdivisionid varchar2(20);
cjobid varchar2(20);
cempid number(10);
begin
cempid :=1;
mypro(cempid,cdivisionid,cjobid);
dbms_output.put_line('...... cdivisionid = '||cdivisionid);
dbms_output.put_line('...... cjobid = '||cjobid);
end;
/
Oracle中的函數:
以下代碼創建了函數:
create or replace function myfun(empid number) return varchar2 is firstName varchar2(20); lastName varchar2(20); begin select first_name,last_name into firstName,lastName from employees2 where employee_id = empid; return 'firstName = '||firstName ||' lastName = '||lastName; end; /
執行以上函數:
declare
fid number(8);
info varchar2(100);
begin
fid :=1;
info :=myfunction(1);
dbms_output.put_line('info ='||info);
end;
/