PL/SQL之基礎篇

PL/SQL之基礎篇

參考文獻:《Oracle完全學習手冊》第11章
原文地址:
http://www.cnblogs.com/sin90lzc/archive/2012/08/26/2646413.html   TimLeung

1.PL/SQL概述

PL/SQL(Procedure Language/Structuer Query Language)是Oracle對標準SQL規範的擴展,全面支持SQL的數據操作、事務控制等。PL/SQL完全支持SQL數據類型,減少了在應用程序和數據庫之間轉換數據的操作。

構成PL/SQL程序的基本單位是程序塊。程序塊由過程、函數和無名塊3種形式組成,它們之間可以互相嵌套。

PL/SQL的運行工具有:SQL*Plus、PL/SQL developer

2.PL/SQL結構

2.1PL/SQL程序塊

PL/SQL程序塊分爲無名塊、命名塊兩種。無名塊指未命名的程序塊,命名塊指過程、函數、包和觸發器等。

PL/SQL塊由3個部分組成:定義部分、執行部分、異常處理部分。PL/SQL塊的基本結構如下:

複製代碼
--DECLARE與EXCEPTION是可選的
[DECLARE
    --定義部分]
BEGIN
    --執行部分
[EXCEPTION
    --異常處理部分]
END;
複製代碼

Notice:DECLARE、BEGIN、EXCEPTION後面沒有分號,而END後則必須要帶有分號

下面是一個PL/SQL塊的一個示例:

複製代碼
SQL> set serveroutput on
SQL> DECLARE
  2     a NUMBER;
  3  BEGIN
  4     a:=1+2;
  5     DBMS_OUTPUT.PUT_LINE('1+2='||a);
  6  EXCEPTION
  7     WHEN OTHERS THEN
  8             DBMS_OUTPUT.PUT_LINE('出現異常');
  9  END;
 10  /
1+2=3

PL/SQL 過程已成功完成。
複製代碼

3.變量的數據類型

按個人的理解,在PL/SQL中,變量的數據類型可以按影響的行列來劃分成以下四種類型:單行單列數據類型、單行多列數據類型、多行單列數據類型、多行多列類型。

在分別詳細介紹了各種變量的數據類型的使用之前,先看一下變量聲明的語法格式:

variable_name [CONSTANT] data_type NOT_NULL [DEFAULT|:=value];

3.1單行單列數據類型

單行單列數據類型也稱爲標量(scalar)數據類型。

標量數據類型大致可以分爲以下四類:

  • Number
  • Charater
  • Data/Time
  • Boolean

表3.1顯示的爲Number類型,表3.2顯示的爲Charater類型,表3.3顯示的是Data/Time及Boolean類型

表3.1 Number類型
Datatype description Subtypes description
BINARY_INTEGER

用於存儲單字節整數。

要求存儲長度低於

NUMBER值

 NATURAL  用於非負數
 NATURALN 只用於非負數和非NULL值 
 POSITIVE 只用於正數
 POSITIVEN 只用於正數,不能用於NULL值 
 SIGNTYPE 只有值:-1,0或1 
 NUMBER

 存儲數字值,包括

整數和浮點數。可以

選擇精度和刻度方式

語法:

number[([,])]

 DECIMAL(DEC)  小數
 DOUBLE PRECISION  雙精度小數
 FLOAT  單精度小數
 INTEGER(INT)  整數
 NUMERIC  與NUMBER等價
 REAL  與NUMBER等價
 SMALLINT  取值範圍比INT小
 PLS_INTEGER

 表示一個有符號整數

範圍:-231到231

運算比NUMBER和

BINARY_INTEGER

都快

   

 

表3.2Character類型
Datatype rage subtypes description
CHAR 最大長度32767字節 CHARACTER 存儲定長字符串,如果長度沒有確定,缺省是1
LONG 最大長度2147483647字節   存儲可變長度字符串
RAW 最大長度32767字節   用於存儲二進制數據和字節字符串,當在兩個數據庫之間時行傳遞時,RAW數據不在字符集之間進行轉換
LONGRAW 最大長度2147483647字節   與LONG數據類型相似,同樣他也不能在字符集之間進行轉換
ROWID 18字節   與數據庫ROWID僞列類型相同,能夠存儲一個行標示符,可以將行標示符看作數據庫中每一行的唯一鍵值。
VARCHAR2 最大長度32767字節   與VARCHAR數據類型相似,存儲可變長度的字符串。聲明方法與VARCHAR相同

 

表3.3Boolean及Date/Time類型
Datatype rang description
BOOLEAN TRUE/FALSE 存儲邏輯值TRUE或FALSE
DATE 01/01/4712 BC 存儲固定長的日期和時間值

 

在PL/SQL中,除了能使用上面說到的數據類型來聲明單行單列變量之外,還可以使用%TYPE變量來聲明單行單列變量. 

使用%TYPE聲明的變量類型與數據表中字段的數據類型相同,當數據表中字段數據類型修改後,PL/SQL程序中相應變量的類型也自動隨之改變.如:

v_name emp.ename%TYPE;

 

3.2單行多列數據類型

3.2.1 %ROWTYPE變量

%ROWTYPE變量用來存儲一行數據.如下面使用%ROWTYPE類型的變量存儲DEPT表中的一行數據:

複製代碼
set serveroutput on
DECLARE
    v_dept dept%ROWTYPE;
BEGIN
    SELECT * into v_dept FROM dept WHERE deptno=30;
    DBMS_OUTPUT.PUT_LINE(v_dept.deptno);
    DBMS_OUTPUT.PUT_LINE(v_dept.dname);
    DBMS_OUTPUT.PUT_LINE(v_dept.loc);
END;
/
複製代碼

 

3.2.2 自定義單行多列數據類型

自定義單行多列數據類型的語法規格如下:

TYPE record_name_type IS RECORD(
    field1_name data_type [NOT NULL][DEFAULT|:=]default_value,
    ...
);

下面是自定義單行多列數據類型的使用例子:

複製代碼
DECLARE
    TYPE emp_record_type IS RECORD(
        name emp.ename%TYPE,
        salary emp.sal%TYPE,
        dno emp.deptno%TYPE
    );
    emp_record emp_record_type;
BEGIN
    SELECT ename,sal,deptno INTO emp_record FROM emp WHERE empno=7788;
    /*也可以這樣使用
    SELECT ename,sal INTO emp_record.name,emp_record.salary FROM emp WHERE empno=7788;
    */
    DBMS_OUTPUT.PUT_LINE(emp_record.name);
END;
/
複製代碼

 

 

3.3 多行單列數據類型

多行單列數據類型或者可以稱其爲集合變量類型.集合類型包括索引表(PL/SQL表),嵌套表(Nested Table)和變長數組(VARRAY)3種類型.下面分別詳細介紹三種集合類型的異同點.

3.3.1索引表(PL/SQL表)

索引表也稱爲PL/SQL表,用於處理PL/SQL數組的數據類型.但是索引表與高級語言的數組是有區別的:高級語言數組的元素個數是有限制的,並且下標不能爲負值;而索引表的元素個數沒有限制,並且下標可以爲負值,甚至可以使用VARCHAR2類型.

PL/SQL中是沒有現成的索引表數據類型的,要使用索引表,必須先進行數據類型定義,其定義語法爲:

TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY key_type;

--type_name:自定義索引表數據類型的名稱(IS TABLE ... INDEX表示索引表類型)
--element_type:用於指定索引表中每個元素的數據類型.如CHAR,NUMBER,VARCHAR2,emp.ename%TYPE等等.
--NOT NULL:表示不允許引用NULL元素
--key_type:用於指定索引表元素下標的數據類型,可以使用(BINARY_INTEGER,PLS_INTEGER或VARCHAR2).

 

Notice:索引表只能作爲PL/SQL複合數據類型使用,而不能作爲表列的數據類型使用.

Example:

複製代碼
DECLARE
    TYPE ename_table_type IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER;
    ename_table ename_table_type;

    TYPE area_table_type IS TABLE OF NUMBER INDEX BY VARCHAR2(10);
    area_table area_table_type;
BEGIN
    SELECT ename INTO ename_table(-1) FROM emp WHERE empno=7788;
    DBMS_OUTPUT.PUT_LINE('僱員號爲7788的僱員名爲'||ename_table(-1));
    SELECT ename INTO ename_table(2) FROM emp WHERE empno=7369;
    DBMS_OUTPUT.PUT_LINE('僱員號爲7369的僱員名爲'||ename_table(2));

    area_table('北京'):=1;
    area_table('上海'):=2;
    area_table('廣州'):=3;
    DBMS_OUTPUT.PUT_LINE('第一個元素:'||area_table.first);
    DBMS_OUTPUT.PUT_LINE('最後一個元素:'||area_table.last);
    DBMS_OUTPUT.PUT_LINE('元素爲"北京"的下一個元素:'||area_table.next('北京'));

END;
/
複製代碼

 

Result:

3.3.2 嵌套表(Nested Table)

嵌套表類型與高級語言數據的區別:高級語言數組的元素下標從0或1開始,並且元素個數是有限制的,元素值是有順序的;而嵌套表的元素下標從1開始,並且元素個數沒有限制,元素值是無序的.

索引表類型與嵌套表類型的區別:索引表類型不能作爲表列的數據類型使用,但嵌套表類型可以作爲表列的數據類型使用.

嵌套表類型與索引表類型一樣,沒有現在的數據類型,要使用嵌套表類型必須首先自定義該類型,自定義嵌套表類型的語法規格如下:

TYPE type_name IS TABLE OF element_type;

--type_name:用於指定嵌套表類型的類型名.
--element_type:用於指定嵌套表內的元素的數據類型.

 

Example:在PL/SQL塊中使用嵌套表

複製代碼
DECLARE
    TYPE ename_table_type IS TABLE OF emp.ename%TYPE;
    ename_table ename_table_type;
BEGIN
    --ename_table:=ename_table_type('','');
    SELECT ename INTO ename_table(2) FROM emp WHERE empno=7788;
    DBMS_OUTPUT.PUT_LINE('僱員名:'||ename_table(2));
END;
/
複製代碼

 

Example:在表列中使用嵌套表

在上面的例子中,會自動地創建表phone_table來保存phone字段的數據。

 

Example:在PL/SQL塊中爲嵌套表列插入數據

BEGIN
    INSERT INTO employee VALUES(1,'SCOTT',800,phone_type('12345678','87654321'));
END;
/

 

Example:在PL/SQL塊中檢索嵌套表列的數據

複製代碼
DECLARE
    phone_table phone_type;
BEGIN
    SELECT phone INTO phone_table FROM employee WHERE id=1;
    FOR i IN 1..phone_table.COUNT LOOP
        DBMS_OUTPUT.PUT_LINE('電話號碼:'||phone_table(i));
    END LOOP;
END;
/
複製代碼

 

Example:在PL/SQL塊中更新嵌套表列的數據

複製代碼
DECLARE
    phone_table phone_type:=phone_type('00000000','11111111');

BEGIN
    UPDATE employee SET phone=phone_table where id=1;
    /*也可以這樣
    UPDATE employee SET phone=phone_type('00000000','11111111') where id=1;
    */
END;
/
複製代碼

 

 

3.3.3變長數組(VARRAY)

變長數組也是一種用於處理PL/SQL數組的數據類型,它也可以作爲表列的數據類型使用.該數據類型與高級語言數組非常相似,其元素下標從1開始,並且元素的最大個數是有限制的.定義VARRAY的語法如下:

TYPE type_name IS VARRAY(size_limit) OF element_type [NOT NULL];

--type_name:用於指定VARRAY類型名
--size_limit:用於指定VARRAY元素的最大個數.
--element_type:用於指定元素的數據類型

 Notice:當使用VARRAY元素時,必須使用其構造方法初始化VARRAY元素

Example:在PL/SQL塊中使用VARRAY

複製代碼
DECLARE
    TYPE ename_table_type IS VARRAY(20) OF emp.ename%TYPE;
    ename_table ename_table_type;
BEGIN
    ename_table:=ename_table_type('','');
    SELECT ename INTO ename_table(2) FROM emp WHERE empno=7788;
    DBMS_OUTPUT.PUT_LINE('僱員名:'||ename_table(2));
END;
/
複製代碼

 

Notice:關於變長數組在表列中的使用可以參考嵌套表,非常類似.唯一的區別是VARRAY不需要使用 NESTED TABLE子句

3.3.4三種集合類型的比較

三種集合類型的異同總結在下表中:

三種集合類型的比較
  索引表 嵌套表 變長數組 高級語言數組
元素下標

可以是負值,甚至使用VARCHAR2類型

從1開始 從1開始 從0或1開始
元素個數限制 無限制 無限制 有限制 有限制
是否需要初始化 不需要 需要 需要 需要
是否可用作表列類型 不可以 可以 可以  

 

3.3.5集合方法

集合方法是Oracle所提供的用於操作集合變量的內置函數或過程,其中EXISTS()、COUNT()、LIMIT()、FIRST()、NEXT()、PRIOR()和LAST()是函數,而EXTEND()、TRIM()和DELETE()則是過程。集合方法的調用語法如下:

collection_name.method_name{(parameters)}

 

Notice:集合方法只能在PL/SQL語句中使用,而不能在SQL語句中調用。另外集合方法EXTEND和TRIM只適合於嵌套表和VARRAY,而不適用於索引表。

下表總結了各方法的使用:

表 集合方法
方法名 用法描述 例子
EXISTS(下標值) 參數的下標值,判斷某個下標的元素時否存在,存在返回TRUE,否則返回FALSE ename_table.EXISTS(1)
COUNT() 返回集合變量中的元素總個數,如果集合元素爲NULL,則統計結果不包含該元素 ename_table.COUNT
LIMIT() 返回集合變量可容元素的最大個數。因爲嵌套表和索引表的元素個數沒有限制,所以返回NULL ename_table.LIMIT
FIRST() 返回集合變量第一個元素的下標 ename_table.FIRST()
LAST() 返回集合變量最後一個元素的下標 ename_table.LAST()
PRIOR(下標值) 返回參數中指定的下標值的前一個元素的下標 ename_table.PRIOR(2)
NEXT(下標值) 返回參數中指定的下標值的下一個元素的下標 ename_table.NEXT(1)

EXTEND

EXTEND(n)

EXTEND(n,i)

(只適用於嵌套表和VARRAY)該方法用於擴展集合變量的尺寸,併爲它們增加元素。其中

EXTEND爲集合變量增加一個NULL元素,EXTEND(n)爲集合變量添加n個NULL元素,而

EXTEND(n,i)爲集合變量增加n個元素(元素值與第i個元素相同)

ename_table.EXTEND(10,1)

TRIM

TRIM(n)

(只適合於嵌套表和VARRAY)

TRIM從集合尾部刪除一個元素,而TRIM(n)從集合尾部刪除n個元素

ename_table.TRIM(2)

DELETE

DELETE(n)

DELETE(m,n)

(只適合於嵌套表和索引表)DELETE用於刪除集合變量的所有元素;DELETE(n)用於刪除集合

變量的第n個元素;而DELETE(m,n)用於刪除集合變量第m到n之間的所有元素

ename_table.DELETE(2,5)

3.4 多行多列數據類型——遊標

在PL/SQL中,針對多行多列的數據類型,可以使用遊標變量。

PL/SQL的遊標指把從數據庫中查詢出來的數據以臨時表的形式存放在內存中.遊標可以對存儲在內存中的數據進行操作,返回一條或一組記錄,或者一條記錄都不返回.

3.4.1遊標的基本操作

遊標包括兩種遊標:隱含遊標和顯式遊標.隱含遊標用於處理SELECT INTO和DML語句,而顯式遊標則專門用於處理SELECT語句返回的多行數據.

遊標的基本操作有:聲明遊標、打開遊標、提取遊標和關閉遊標。

下面的代碼塊展示了這四個基本操作:

複製代碼
DECLARE
    CURSOR c_emp IS SELECT * FROM EMP; --聲明遊標
    emp_record emp%ROWTYPE;
BEGIN
    OPEN c_emp; --打開遊標
    LOOP
        FETCH c_emp INTO emp_record; --提取遊標
        DBMS_OUTPUT.PUT_LINE('僱員名稱:'||emp_record.ename);
    EXIT WHEN c_emp%NOTFOUND;
    END LOOP;
    CLOSE c_emp; --關閉遊標
END;
/
複製代碼

3.4.2遊標屬性

遊標作爲一個臨時表,可以通過遊標的屬性來獲取遊標狀態.遊標有4個常用的屬性:

  1. %ISOPEN:用於判斷遊標是否已經打開
  2. %FOUND:用於判斷遊標是否找到記錄
  3. %NOTFOUND:與%FOUND相反.
  4. %ROWCOUNT:返回到當前爲止已經提取到的實際行數.

3.4.3參數化遊標

參數化遊標是指帶有參數的遊標,在定義了參數遊標之後,當使用不同的參數值多次打開遊標時,可以生成不同的結果集.參數化遊標的聲明語法如下:

CURSOR cursor_name(parameter) IS SELECE ...

 

Example:參數化遊標的使用

複製代碼
DECLARE
    CURSOR emp_cursor(dno NUMBER) IS 
    SELECT ename FROM emp WHERE deptno=dno;
    v_ename emp.ename%TYPE;
BEGIN
    OPEN emp_cursor(10);
    LOOP
        FETCH emp_cursor INTO v_ename;
        EXIT WHEN emp_cursor%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE(v_ename);
    END LOOP;
    CLOSE emp_cursor;
END;
/
複製代碼

 

3.4.4隱式遊標

隱式遊標就是指非PL/SQL程序中定義的,而且是在PL/SQL中使用UPDATE、DELETE或SELECT INTO語句時,Oracle系統自動分配的遊標。隱式遊標名稱固定爲SQL。隱式遊標無須聲明和打開,使用完後也不用關閉,所有這一切都由系統自動維護。

Example:SELECT INTO的隱式遊標

複製代碼
DECLARE
    v_emp emp%ROWTYPE;
BEGIN
    SELECT * INTO v_emp FROM emp WHERE empno=7788;
    IF SQL%FOUND THEN
        DBMS_OUTPUT.PUT_LINE('7788的僱員名稱:'||v_emp.ename);
    END IF;
END;
/
複製代碼

 

Example:UPDATE的隱式遊標

複製代碼
BEGIN
    UPDATE emp SET ename='SCOTT' WHERE empno=7788;
    IF SQL%FOUND THEN
        DBMS_OUTPUT.PUT_LINE('更新成功!');
    END IF;
END;
/
複製代碼

 

3.4.5使用遊標更新或刪除數據

通過使用顯式遊標,不僅可以一行一行地處理SELECT語句的結果,而且也可以更新或刪除當前遊標行的數據。在使用遊標更新或刪除數據時有兩點需要注意的地方:

  1. 聲明遊標是必須帶有FOR UPDATE子句,如:
    CURSOR cursor_name IS SELECT ... FOR UPDATE;
  2. 在提取了遊標數據之後,爲了更新或刪除當前遊標行數據,必須在UPDATE或DELETE語句中引用WHERE CURRENT OF子句。如:
    UPDATE table_name SET column=... WHERE CURRENT OF cursor_name;
    DELETE table_name WHERE CURRENT OF cursor_name;

     

Example:使用遊標更新數據

複製代碼
DECLARE
    CURSOR emp_cursor IS SELECT ename,sal FROM emp FOR UPDATE;
    v_ename emp.ename%TYPE;
    v_sal emp.sal%TYPE;
BEGIN
    OPEN emp_cursor;
    LOOP
        FETCH emp_cursor INTO v_ename,v_sal;
        EXIT WHEN emp_cursor%NOTFOUND;
        IF v_sal<2000 THEN
            UPDATE emp SET sal=sal+100 WHERE CURRENT OF emp_cursor;
        END IF;
    END LOOP;
    CLOSE emp_cursor;
END;
/
複製代碼

 

 

3.4.6 遊標FOR循環

當使用遊標FOR循環時,Oracle會隱含地打開遊標、提取遊標數據並關閉遊標。

Example:使用遊標FOR循環

複製代碼
DECLARE
    CURSOR emp_cursor IS SELECT * FROM emp;
    v_emp emp%ROWTYPE;
BEGIN
    FOR v_emp IN emp_cursor LOOP
        DBMS_OUTPUT.PUT_LINE(''||emp_cursor%ROWCOUNT||'個僱員'||v_emp.ename);
    END LOOP;
END;
/
複製代碼

 

Example: 在遊標FOR循環中直接使用子查詢

複製代碼
DECLARE
    v_emp emp%ROWTYPE;
BEGIN
    FOR v_emp IN (SELECT * FROM EMP) LOOP
        DBMS_OUTPUT.PUT_LINE('編號'||v_emp.empno||'的僱員名稱:'||v_emp.ename);
    END LOOP;
END;
/
複製代碼

 

3.4.7 遊標變量

上面提到的顯式遊標和隱式遊標都與固定的查詢語句相關聯,所以稱之爲靜態遊標。遊標變量與靜態遊標不同,它是一種動態遊標,在運行期間可以與不同的查詢語句相關聯。

要聲明遊標變量,首先得創建一個遊標數據類型,創建遊標數據類型的語法如下:

TYPE cursor_data_type_name IS REF CURSOR [RETURN return_type];

 Example:操作遊標變量

複製代碼
DECLARE
    TYPE emp_cursor_type IS REF CURSOR RETURN emp%ROWTYPE;
    emp_cursor emp_cursor_type;
    emp_record emp%ROWTYPE;
BEGIN
    IF NOT emp_cursor%ISOPEN THEN
        OPEN emp_cursor FOR SELECT * FROM emp WHERE deptno=10;
    END IF;
    LOOP
        FETCH emp_cursor INTO emp_record;
        EXIT WHEN emp_cursor%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE('僱員名:'||emp_record.ename);
    END LOOP;
END;
/
複製代碼

 

4 PL/SQL的控制結構

4.1 IF語句

IF語句的語法:

複製代碼
IF condition1 THEN
    statement1;
ELSIF condition2 THEN
    statement2;
ELSE
    statement3;
END IF;
複製代碼

 

4.2 CASE語句

CASE語句語法:

複製代碼
CASE variable_name 
WHEN case1 THEN statement1;
WHEN case2 THEN statement2;
...
WHEN caseN-1 THEN statementN-1;
[ELSE statementN]
END CASE;
複製代碼

Example:CASE語句的使用

複製代碼
DECLARE
    grade CHAR :='B';
    appraisal VARCHAR2(20);
BEGIN
    appraisal :=
    CASE grade
        WHEN 'A' THEN ''
        WHEN 'B' THEN ''
        ELSE '不及格'
    END;
    DBMS_OUTPUT.PUT_LINE('Grade '||grade|| ' is '||appraisal);
    
    /*下面效果一樣
    grade:='A';
    CASE grade
        WHEN 'A' THEN appraisal :='優';
        WHEN 'B' THEN appraisal :='良';
        ELSE appraisal :='不及格';
    END CASE;
    DBMS_OUTPUT.PUT_LINE('Grade '||grade|| ' is '||appraisal);
    
    */
END;
/
複製代碼

 

4.3基本循環

基本循環的語法:

LOOP
    statements
    EXIT [WHEN condition]
END LOOP;

 

4.4WHILE循環

WHILE循環語法:

WHILE condition LOOP
    statements;
END LOOP;

4.5 FOR循環

FOR循環語法

FOR loop_variable IN [REVERSE] lower_bound..upper_bound LOOP
    statements;
END LOOP;

 

Example:FOR循環的使用

複製代碼
DECLARE
    i INTEGER;
BEGIN
    FOR i IN REVERSE 1..3 LOOP
        DBMS_OUTPUT.PUT_LINE(i);
    END LOOP;
END;
/
複製代碼

 

5 異常處理

Oracle系統中的異常分爲系統預定義異常和用戶自定義異常。異常處理的一般語法如下:

複製代碼
EXCEPTION
    WHEN exception1 THEN
        statements1;
    WHEN exception2 THEN
        statements2;
    WHEN OTHERS THEN
        statements3;
複製代碼

5.1系統預定義異常

常用的系統預定義異常
錯誤信息 異常錯誤名稱 說明
ORA-0001 Dup_val_on_index 試圖破壞一個唯一性限制
ORA-0051 Timeout-on-resource 在等待資源時發生超時
ORA-0061 Transaction-backed-out 由於發生死鎖事務被撤銷
ORA-1001 Invalid-CURSOR 試圖使用一個無效的遊標
ORA-1012 Not-logged-on 沒有連接到Oracle
ORA-1017 Login-denied 無效的用戶名/口令
ORA-1403 NO_DATA_FOUND SELECT INTO沒有找到數據
ORA-1422 TOO_MANY_ROWS SELECT INTO 返回多行
ORA-1476 Zero-divide 試圖被零除
ORA-1722 Invalid-NUMBER 轉換一個數字失敗
ORA-6500 Stroage-error 內存不夠引發的內部錯誤
ORA-6501 Program-error 內部錯誤
ORA-6502 Value-error 轉換或截斷錯誤
ORA-6504 Rowtype-mismatch 主變量和遊標的類型不兼容
ORA-6511 CURSOR-ALERADY-OPEN 試圖打開一個已經打開的遊標
ORA-6530 ACCESS_INTO_NULL 試圖爲null對象的屬性賦值(如一個對象沒初始化時,向其內部屬性賦值)

Example:NO_DATA_FOUND異常的處理

複製代碼
DECLARE
    v_sal emp.sal%TYPE;
BEGIN
    SELECT SAL INTO v_sal FROM emp WHERE ename='MARY';
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('不存在該僱員!');
END;
/
複製代碼

 

5.2用戶自定義異常

用戶自定義異常的語法:

exception_name EXCEPTION;
PRAGMA EXCEPTION_INTO(exception_name,exception_no);

--PRAGMA關鍵字用於把某個異常名和異常號關聯起來

在聲明瞭自定義異常後,便可以使用RAISE語句顯式觸發異常了。

Example:觸發用戶自定義異常

複製代碼
DECLARE
    e_no_employee EXCEPTION;
    PRAGMA EXCEPTION_INIT(e_no_employee,-2291);
BEGIN
    UPDATE emp SET deptno=10 WHERE empno=1111;
    IF SQL%NOTFOUND THEN
        RAISE e_no_employee;
    END IF;
EXCEPTION
    WHEN e_no_employee THEN
        DBMS_OUTPUT.PUT_LINE('該僱員不存在!');
END;
/
複製代碼

 

 

5.3異常函數

  1. SQLCODE()和SQLERRM()
    SQLCODE()用於返回Oracle錯誤號,而SQLERRM()用於返回該錯誤號對應的錯誤消息。

  2. RAISE_APPLICATION_ERROR
    該過程用於在 PL/SQL應用程序中自定義錯誤消息。該過程只能在(過程、函數、包、觸發器)中使用。

Example:SQLCODE()和SQLERRM()的使用

複製代碼
DECLARE
    v_ename emp.ename%TYPE;
BEGIN
    SELECT ename INTO v_ename FROM emp WHERE deptno=10;
    DBMS_OUTPUT.PUT_LINE('僱員名:'||v_ename);
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('僱員不存在!');
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('錯誤號:'||SQLCODE);
        DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/
複製代碼

 

Example:RAISE_APPLICATION_ERROR的使用(略)

  RAISE_APPLICATION_ERROR('-20001','該僱員無補助');

 

發佈了42 篇原創文章 · 獲贊 5 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章