PL/SQL之基礎篇


參考文獻:《Oracle完全學習手冊》第11章

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','該雇員無補助');

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM