ORACLE PL/SQL編程詳解
SQL語言只是訪問、操作數據庫的語言,並不是一種具有流程控制的程序設計語言,而只有程序設計語言才能用於應用軟件的開發。PL /SQL是一種高級數據庫程序設計語言,該語言專門用於在各種環境下對Oracle數據庫進行訪問。由於該語言集成於數據庫服務器中,所以PL/SQL代碼可以對數據進行快速高效的處理。除此之外,可以在oracle數據庫的某些客戶端工具中,使用PL/SQL語言也是該語言的一個特點。本章的主要內容是討論引入PL/SQL語言的必要性和該語言的主要特點,以及了解PL/SQL語言的重要性和數據庫版本問題。還要介紹一些貫穿全書的更詳細的高級概念,並在本章的最后就我們在本書案例中使用的數據庫表的若干約定做一說明。
1.1 SQL與PL/SQL
1.1.1 什么是PL/SQL?
PL/SQL是 Procedure Language & Structured Query Language 的縮寫。ORACLE的SQL是支持ANSI(American national Standards Institute)和ISO92 (International Standards Organization)標准的產品。PL/SQL是對SQL語言存儲過程語言的擴展。從ORACLE6以后,ORACLE的RDBMS附帶了PL/SQL。它現在已經成為一種過程處理語言,簡稱PL/SQL。目前的PL/SQL包括兩部分,一部分是數據庫引擎部分;另一部分是可嵌入到許多產品(如C語言,Java語言等)工具中的獨立引擎。可以將這兩部分稱為:數據庫PL/SQL和工具PL/SQL。兩者的編程非常相似。都具有編程結構、語法和邏輯機制。工具PL/SQL另外還增加了用於支持工具(如ORACLE Forms)的句法,如:在窗體上設置按鈕等。本章主要介紹數據庫PL/SQL內容。
1.2 PL/SQL的優點或特征
1.2.1 有利於客戶/服務器環境應用的運行
對於客戶/服務器環境來說,真正的瓶頸是網絡上。無論網絡多快,只要客戶端與服務器進行大量的數據交換。應用運行的效率自然就回受到影響。如果使用PL/SQL進行編程,將這種具有大量數據處理的應用放在服務器端來執行。自然就省去了數據在網上的傳輸時間。
1.2.2 適合於客戶環境
PL/SQL由於分為數據庫PL/SQL部分和工具PL/SQL。對於客戶端來說,PL/SQL可以嵌套到相應的工具中,客戶端程序可以執行本地包含PL/SQL部分,也可以向服務發SQL命令或激活服務器端的PL/SQL程序運行。
1.2.3 過程化
PL/SQL是Oracle在標准SQL上的過程性擴展,不僅允許在PL/SQL程序內嵌入SQL語句,而且允許使用各種類型的條件分支語句和循環語句,可以多個應用程序之間共享其解決方案。
1.2.4 模塊化
PL/SQL程序結構是一種描述性很強、界限分明的塊結構、嵌套塊結構,被分成單獨的過程、函數、觸發器,且可以把它們組合為程序包,提高程序的模塊化能力。
1.2.5 運行錯誤的可處理性
使用PL/SQL提供的異常處理(EXCEPTION),開發人員可集中處理各種ORACLE錯誤和PL/SQL錯誤,或處理系統錯誤與自定義錯誤,以增強應用程序的健壯性。
1.2.6 提供大量內置程序包
ORACLE提供了大量的內置程序包。通過這些程序包能夠實現DBS的一些低層操作、高級功能,不論對DBA還是應用開發人員都具有重要作用。
當然還有其它的一些優點如:更好的性能、可移植性和兼容性、可維護性、易用性與快速性等。
1.3 PL/SQL 可用的SQL語句
PL/SQL是ORACLE系統的核心語言,現在ORACLE的許多部件都是由PL/SQL寫成。在PL/SQL中可以使用的SQL語句有:
INSERT,UPDATE,DELETE,SELECT INTO,COMMIT,ROLLBACK,SAVEPOINT。
提示:在 PL/SQL中只能用 SQL語句中的 DML 部分,不能用 DDL 部分,如果要在PL/SQL中使用DDL(如CREATE table 等)的話,只能以動態的方式來使用。
l ORACLE 的 PL/SQL 組件在對 PL/SQL 程序進行解釋時,同時對在其所使用的表名、列名及數據類型進行檢查。
l PL/SQL 可以在SQL*PLUS 中使用。
l PL/SQL 可以在高級語言中使用。
l PL/SQL可以在ORACLE的開發工具中使用(如:SQL Developer或Procedure Builder等)。
l 其它開發工具也可以調用PL/SQL編寫的過程和函數,如Power Builder 等都可以調用服務器端的PL/SQL過程。
1.4 運行PL/SQL程序
PL/SQL程序的運行是通過ORACLE中的一個引擎來進行的。這個引擎可能在ORACLE的服務器端,也可能在 ORACLE 應用開發的客戶端。引擎執行PL/SQL中的過程性語句,然后將SQL語句發送給數據庫服務器來執行。再將結果返回給執行端
2.1 PL/SQL塊
PL/SQL程序由三個塊組成,即聲明部分、執行部分、異常處理部分。
PL/SQL塊的結構如下:
DECLARE --聲明部分: 在此聲明PL/SQL用到的變量,類型及游標,以及局部的存儲過程和函數 BEGIN -- 執行部分: 過程及SQL 語句 , 即程序的主要部分 EXCEPTION -- 執行異常部分: 錯誤處理 END;
其中:執行部分不能省略。
PL/SQL塊可以分為三類:
1. 無名塊或匿名塊(anonymous):動態構造,只能執行一次,可調用其它程序,但不能被其它程序調用。
2. 命名塊(named):是帶有名稱的匿名塊,這個名稱就是標簽。
3. 子程序(subprogram):存儲在數據庫中的存儲過程、函數等。當在數據庫上建立好后可以在其它程序中調用它們。
4. 觸發器 (Trigger):當數據庫發生操作時,會觸發一些事件,從而自動執行相應的程序。
5. 程序包(package):存儲在數據庫中的一組子程序、變量定義。在包中的子程序可以被其它程序包或子程序調用。但如果聲明的是局部子程序,則只能在定義該局部子程序的塊中調用該局部子程序。
2.2 PL/SQL結構
l PL/SQL塊中可以包含子塊;
l 子塊可以位於 PL/SQL中的任何部分;
l 子塊也即PL/SQL中的一條命令;
2.3 標識符
PL/SQL程序設計中的標識符定義與SQL 的標識符定義的要求相同。要求和限制有:
l 標識符名不能超過30字符;
l 第一個字符必須為字母;
l 不分大小寫;
l 不能用’-‘(減號);
l 不能是SQL保留字。
提示: 一般不要把變量名聲明與表中字段名完全一樣,如果這樣可能得到不正確的結果.
例如:下面的例子將會刪除所有的紀錄,而不是’EricHu’的記錄;
DECLARE ename varchar2(20) :='EricHu'; BEGIN DELETE FROM scott.emp WHERE ename=ename; END;
標識符 |
命名規則 |
例子 |
程序變量 |
V_name |
V_name |
程序常量 |
C_Name |
C_company_name |
游標變量 |
Cursor_Name |
Cursor_Emp |
異常標識 |
E_name |
E_too_many |
表類型 |
Name_table_type |
Emp_record_type |
表 |
Name_table |
Emp |
記錄類型 |
Name_record |
Emp_record |
SQL*Plus 替代變量 |
P_name |
P_sal |
綁定變量 |
G_name |
G_year_sal |
變量命名在PL/SQL中有特別的講究,建議在系統的設計階段就要求所有編程人員共同遵守一定的要求,使得整個系統的文檔在規范上達到要求。下面是建議的命名方法:
2.4 PL/SQL 變量類型
在前面的介紹中,有系統的數據類型,也可以自定義數據類型。下表給出ORACLE類型和PL/SQL中的變量類型的合法使用列表:
2.4.1 變量類型
在ORACLE8i中可以使用的變量類型有:
類型 |
子類 |
說 明 |
范 圍 |
ORACLE限制 |
CHAR |
Character String Rowid Nchar |
定長字符串
民族語言字符集 |
0à32767 可選,確省=1 |
2000 |
VARCHAR2 |
Varchar, String NVARCHAR2 |
可變字符串 民族語言字符集 |
0à32767 4000 |
4000 |
BINARY_INTEGER |
|
帶符號整數,為整數計算優化性能 |
|
|
NUMBER(p,s) |
Dec
Double precision Integer Int Numeric Real Small int |
小數, NUMBER 的子類型 高精度實數 整數, NUMBER 的子類型 整數, NUMBER 的子類型 與NUMBER等價 與NUMBER等價 整數, 比 integer 小 |
|
|
LONG |
|
變長字符串 |
0->2147483647 |
32,767字節 |
DATE |
|
日期型 |
公元前4712年1月1日至公元后4712年12月31日 |
|
BOOLEAN |
|
布爾型 |
TRUE, FALSE,NULL |
不使用 |
ROWID |
|
存放數據庫行號 |
|
|
UROWID |
|
通用行標識符,字符類型 |
|
|
|
|
|
|
|
例1. 插入一條記錄並顯示;
DECLARE Row_id ROWID; info VARCHAR2(40); BEGIN INSERT INTO scott.dept VALUES (90, '財務室', '海口') RETURNING rowid, dname||':'||to_char(deptno)||':'||loc INTO row_id, info; DBMS_OUTPUT.PUT_LINE('ROWID:'||row_id); DBMS_OUTPUT.PUT_LINE(info); END;
RETURNING子句用於檢索INSERT語句中所影響的數據行數,當INSERT語句使用VALUES 子句插入數據時,RETURNING 字句還可將列表達式、ROWID和REF值返回到輸出變量中。在使用RETURNING 子句是應注意以下幾點限制:其中:
1.不能與DML語句和遠程對象一起使用;
2.不能檢索LONG 類型信息;
3.當通過視圖向基表中插入數據時,只能與單基表視圖一起使用。
例2. 修改一條記錄並顯示其中:
DECLARE Row_id ROWID; info VARCHAR2(40); BEGIN UPDATE dept SET deptno=100 WHERE DNAME='財務室' RETURNING rowid, dname||':'||to_char(deptno)||':'||loc INTO row_id, info; DBMS_OUTPUT.PUT_LINE('ROWID:'||row_id); DBMS_OUTPUT.PUT_LINE(info); END;
RETURNING子句用於檢索被修改行的信息。當UPDATE語句修改單行數據時,RETURNING 子句可以檢索被修改行的ROWID和REF值,以及行中被修改列的列表達式,並可將他們存儲到PL/SQL變量或復合變量中;當UPDATE語句修改多行數據時,RETURNING 子句可以將被修改行的ROWID和REF值,以及列表達式值返回到復合變量數組中。在UPDATE中使用RETURNING 子句的限制與INSERT語句中對RETURNING子句的限制相同。
例3. 刪除一條記錄並顯示
DECLARE Row_id ROWID; info VARCHAR2(40); BEGIN DELETE dept WHERE DNAME='辦公室' RETURNING rowid, dname||':'||to_char(deptno)||':'||loc INTO row_id, info; DBMS_OUTPUT.PUT_LINE('ROWID:'||row_id); DBMS_OUTPUT.PUT_LINE(info); END;
RETURNING子句用於檢索被刪除行的信息:當DELETE語句刪除單行數據時,RETURNING 子句可以檢索被刪除行的ROWID和REF值,以及被刪除列的列表達式,並可將他們存儲到PL/SQL變量或復合變量中;當DELETE語句刪除多行數據時,RETURNING 子句可以將被刪除行的ROWID和REF值,以及列表達式值返回到復合變量數組中。在DELETE中使用RETURNING 子句的限制與INSERT語句中對RETURNING子句的限制相同。 其中: