第四章異常處理
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; /