Oracle PL/SQL語言初級教程
PL/SQL 語言基礎 PL/SQL 是一種高性能的基於事務處理的語言,能運行在任何 ORACLE 環境中,支持全部數據處理命令。 經過使用 PL/SQL 程序單元處理 SQL 的數據定義和數據控制元素。 • Oracle PL/SQL語言基礎(1) • Oracle PL/SQL語言基礎(2) • Oracle PL/SQL語言基礎(3)
複合數據類型 PL/SQL 有兩種複合數據結構:記錄和集合。記錄由不一樣的域組成,集合由不一樣的元素組成。在本文中我 們將討論記錄和集合的類型、怎樣定義和使用記錄和集合。 • 複合數據類型(1) • 複合數據類型(2) • 複合數據類型(3) • 複合數據類型(4) • 複合數據類型(5)
單行函數和組函數 函數是一種有零個或多個參數而且有一個返回值的程序。在 SQL 中 Oracle 內建了一系列函數,這些函數 均可被稱爲 SQL 或 PL/SQL 語句,函數主要分爲兩大類:單行函數和組函數。 • 單行函數和組函數詳解(1) • 單行函數和組函數詳解(2) • 單行函數和組函數詳解(3) • 單行函數和組函數詳解(4) • 單行函數和組函數詳解(5)
表和視圖 Oracle 中表是數據存儲的基本結構。Oracle 中引入了分區表和對象表,視圖是一個或多個表中數據的邏輯 表達式。本文咱們將討論怎樣建立和管理簡單的表和視圖。 • 表和視圖(1) • 表和視圖(2)
完整性約束 完整性約束是一種規則,不佔用任何數據庫空間。完整性約束存在數據字典中,在執行 SQL 或 PL/SQL 期 間使用。用戶能夠指明約束是啓用的仍是禁用的,當約束啓用時,他加強了數據的完整性,不然,則反之, 但約束始終存在於數據字典中。 • 完整性約束(1) • 完整性約束(2) • 完整性約束(3)
過程和函數 過程和函數都以編譯後的形式存放在數據庫中,函數能夠沒有參數也能夠有多個參數並有一個返回值。過
程有零個或多個參數,沒有返回值。函數和過程均可以經過參數列表接收或返回零個或多個值,函數和過 程的主要區別不在於返回值,而在於他們的調用方式。
• 過程和函數(1) • 過程和函數(2)
操做和控制語言 SQL 語言共分爲四大類:數據查詢語言 DQL,數據操縱語言 DML, 數據定義語言 DDL,數據控制語言 DCL。其中用於定義數據的結構,好比 建立、修改或者刪除數據庫;DCL 用於定義數據庫用戶的權限。 • 數據操做和控制語言詳解(1) • 數據操做和控制語言詳解(2) • 數據操做和控制語言詳解(3)
遊標 當執行一條 DML 語句後,DML 語句的結果保存在四個遊標屬性中,這些屬性用於控制程序流程或者瞭解 程序的狀態。當運行 DML 語句時,PL/SQL 打開一個內建遊標並處理結果,遊標是維護查詢結果的內存中 的一個區域。 • 遊標使用大全(1) • 遊標使用大全(2) • 遊標使用大全(3)
異常處理 PL/SQL 處理異常不一樣於其餘程序語言的錯誤管理方法,PL/SQL 的異常處理機制與 ADA 很類似,有一個 處理錯誤的全包含方法。 • 異常處理初步(1) • 異常處理初步(2)
PL/SQL 語言基礎
Oracle PL/SQL 語言基礎(1)
PL/SQL 是 ORACLE 對標準數據庫語言的擴展,ORACLE 公司已經將 PL/SQL 整合到
ORACLE 服務器和其餘工具中了,近幾年中更多的開發人員和 DBA 開始使用 PL/SQL,本
文將講述 PL/SQL 基礎語法,結構和組件、以及如何設計並執行一個 PL/SQL 程序。
PL/SQL 的優勢
從版本 6 開始 PL/SQL 就被可靠的整合到 ORACLE 中了,一旦掌握 PL/SQL 的優勢以
及其獨有的數據管理的便利性,那麼你很難想象 ORACLE 缺了 PL/SQL 的情形。PL/SQL 不
是一個獨立的產品,他是一個整合到 ORACLE 服務器和 ORACLE 工具中的技術,能夠把
PL/SQL 看做 ORACLE 服務器內的一個引擎,sql 語句執行者處理單個的 sql 語句,PL/SQL
引擎處理 PL/SQL 程序塊。當 PL/SQL 程序塊在 PL/SQL 引擎處理時,ORACLE 服務器中
的 SQL 語句執行器處理 pl/sql 程序塊中的 SQL 語句。
PL/SQL 的優勢以下:
. PL/SQL 是一種高性能的基於事務處理的語言,能運行在任何 ORACLE 環境中,支持
全部數據處理命令。經過使用 PL/SQL 程序單元處理 SQL 的數據定義和數據控制元素。
. PL/SQL 支持全部 SQL 數據類型和全部 SQL 函數,同時支持全部 ORACLE 對象類型
. PL/SQL 塊能夠被命名和存儲在 ORACLE 服務器中,同時也能被其餘的 PL/SQL 程序
或 SQL 命令調用,任何客戶/服務器工具都能訪問 PL/SQL 程序,具備很好的可重用性。
. 可使用 ORACLE 數據工具管理存儲在服務器中的 PL/SQL 程序的安全性。能夠授
權或撤銷數據庫其餘用戶訪問 PL/SQL 程序的能力。
. PL/SQL 代碼可使用任何 ASCII 文本編輯器編寫,因此對任何 ORACLE 可以運行的
操做系統都是很是便利的
. 對於 SQL,ORACLE 必須在同一時間處理每一條 SQL 語句,在網絡環境下這就意味
做每個獨立的調用都必須被 oracle 服務器處理,這就佔用大量的服務器時間,同時致使
網絡擁擠。而 PL/SQL 是以整個語句塊發給服務器,這就下降了網絡擁擠。
PL/SQL 塊結構
PL/SQL 是一種塊結構的語言,組成 PL/SQL 程序的單元是邏輯塊,一個 PL/SQL 程序
包含了一個或多個邏輯塊,每一個塊均可以劃分爲三個部分。與其餘語言相同,變量在使用之
前必須聲明,PL/SQL 提供了獨立的專門用於處理異常的部分,下面描述了 PL/SQL 塊的不
同部分:
聲明部分(Declaration section)
聲明部分包含了變量和常量的數據類型和初始值。這個部分是由關鍵字 DECLARE 開
始,若是不須要聲明變量或常量,那麼能夠忽略這一部分;須要說明的是遊標的聲明也在這
一部分。
執行部分(Executable section)
執行部分是 PL/SQL 塊中的指令部分,由關鍵字 BEGIN 開始,全部的可執行語句都放
在這一部分,其餘的 PL/SQL 塊也能夠放在這一部分。
異常處理部分(Exception section)
這一部分是可選的,在這一部分中處理異常或錯誤,對異常處理的詳細討論咱們在後面
進行。 ios
PL/SQL 塊語法
[DECLARE] ---declaration statements BEGIN ---executable statements [EXCEPTION] ---exception statements END
PL/SQL 塊中的每一條語句都必須以分號結束,SQL 語句可使多行的,但分號表示該
語句的結束。一行中能夠有多條 SQL 語句,他們之間以分號分隔。每個 PL/SQL 塊由
BEGIN 或 DECLARE 開始,以 END 結束。註釋由--標示。
PL/SQL 塊的命名和匿名
PL/SQL 程序塊能夠是一個命名的程序塊也能夠是一個匿名程序塊。匿名程序塊能夠用
在服務器端也能夠用在客戶端。
命名程序塊能夠出如今其餘 PL/SQL 程序塊的聲明部分,這方面比較明顯的是子程序,
子程序能夠在執行部分引用,也能夠在異常處理部分引用。
PL/SQL 程序塊可背獨立編譯並存儲在數據庫中,任何與數據庫相鏈接的應用程序均可
以訪問這些存儲的 PL/SQL 程序塊。ORACLE 提供了四種類型的可存儲的程序:
. 函數
. 過程
. 包
. 觸發器
函數
函數是命名了的、存儲在數據庫中的 PL/SQL 程序塊。函數接受零個或多個輸入參數,
有一個返回值,返回值的數據類型在建立函數時定義。定義函數的語法以下:
FUNCTION name [{parameter[,parameter,...])] RETURN datatypes IS [local declarations] BEGIN execute statements [EXCEPTION exception handlers] END [name]
過程
存儲過程是一個 PL/SQL 程序塊,接受零個或多個參數做爲輸入(INPUT)或輸出
(OUTPUT)、或既做輸入又做輸出(INOUT),與函數不一樣,存儲過程沒有返回值,存儲過程
不能由 SQL 語句直接使用,只能經過 EXECUT 命令或 PL/SQL 程序塊內部調用,定義存
儲過程的語法以下:
PROCEDURE name [(parameter[,parameter,...])] IS [local declarations] BEGIN execute statements
[EXCEPTION exception handlers ] END [name]
包(package)
包其實就是被組合在一塊兒的相關對象的集合,當包中任何函數或存儲過程被調用,包就
被加載入內存中,包中的任何函數或存儲過程的子程序訪問速度將大大加快。
包由兩個部分組成:規範和包主體(body),規範描述變量、常量、遊標、和子程序,包體完
全定義子程序和遊標。
觸發器(trigger)
觸發器與一個表或數據庫事件聯繫在一塊兒的,當一個觸發器事件發生時,定義在表上的
觸發器被觸發。
PL/SQL 語言基礎
Oracle PL/SQL 語言基礎(2)
變量和常量
變量存放在內存中以得到值,能被 PL/SQL 塊引用。你能夠把變量想象成一個可儲藏東
西的容器,容器內的東西是能夠改變的。 程序員
聲明變量
變量通常都在 PL/SQL 塊的聲明部分聲明,PL/SQL 是一種強壯的類型語言,這就是說
在引用變量前必須首先聲明,要在執行或異常處理部分使用變量,那麼變量必須首先在聲明
部分進行聲明。
聲明變量的語法以下:
Variable_name [CONSTANT] databyte [NOT NULL][:=|DEFAULT expression]
注意 :能夠在聲明變量的同時給變量強制性的加上 NOT NULL 約束條件,此時變量在初
始化時必須賦值。
給變量賦值
給變量賦值有兩種方式:
. 直接給變量賦值
X:=200;
Y=Y+(X*20);
. 經過 SQL SELECT INTO 或 FETCH INTO 給變量賦值
SELECT SUM(SALARY),SUM(SALARY*0.1)
INTO TOTAL_SALARY,TATAL_COMMISSION
FROM EMPLOYEE
WHERE DEPT=10;
常量
常量與變量類似,但常量的值在程序內部不能改變,常量的值在定義時賦予,,他的聲
明方式與變量類似,但必須包括關鍵字 CONSTANT。常量和變量均可被定義爲 SQL 和用
戶定義的數據類型。
ZERO_VALUE CONSTANT NUMBER:=0;
這個語句定了一個名叫 ZERO_VALUE、數據類型是 NUMBER、值爲 0 的常量。
標量(scalar)數據類型
標量(scalar)數據類型沒有內部組件,他們大體可分爲如下四類:
. number
. character
. date/time
. boolean
表1 顯示了數字數據類型;表 2 顯示了字符數據類型;表 3 顯示了日期和布爾數據類
型。
表1 Scalar Types:Numeric
Datatype Range Subtypes description
BINARY_INTEGER -214748-2147483647 NATURAL NATURAL NPOSITIVE POSITIVEN SIGNTYPE
用於存儲單字節整數。 要求存儲長度低於 NUMBER 值。 用於限制範圍的子類型(SUBTYPE): NATURAL:用於非負數 POSITIVE:只用於正數 NATURALN:只用於非負數和非 NULL 值 POSITIVEN:只用於正數,不能用於 NULL 值 SIGNTYPE:只有值:-一、0 或 1.
NUMBER 1.0E-130-9.99E125 DEC DECIMAL DOUBLE PRECISION FLOAT INTEGERIC INT NUMERIC REAL SMALLINT 存儲數字值,包括整數和浮點數。能夠選擇 精度和刻度方式,語法: number[([,])]。 缺省的精度是 38,scale 是 0.
PLS_INTEGER -2147483647-2147483647
與 BINARY_INTEGER 基本相同,但採用機 器運算時,PLS_INTEGER 提供更好的性 能 。
表2 字符數據類型
datatype rang subtype description
CHAR
大長度 32767 字 節
CHARACTER 存儲定長字符串,若是長度沒有肯定,缺省是 1
LONG
大長度 2147483647 字節
存儲可變長度字符串
RAW
大長度 32767 字 節
用於存儲二進制數據和字節字符串,當在兩個數據庫 之間進行傳遞時,RAW 數據不在字符集之間進行轉 換。
LONGRAW
大長度 2147483647
與 LONG 數據類型類似,一樣他也不能在字符集之 間進行轉換。
ROWID 18 個字節
與數據庫 ROWID 僞列類型相同,可以存儲一個行標 示符,能夠將行標示符看做數據庫中每一行的惟一鍵 值。
VARCHAR2
大長度 32767 字 節
STRINGVARCHAR
與 VARCHAR 數據類型類似,存儲可變長度的字符 串。聲明方法與 VARCHAR 相同
表3 DATE 和 BOOLEAN
datatype range description
BOOLEAN TRUE/FALSE 存儲邏輯值 TRUE 或 FALSE,無參數
DATE 01/01/4712 BC 存儲固定長的日期和時間值,日期值中包含時間
LOB 數據類型
LOB(大對象,Large object) 數據類型用於存儲相似圖像,聲音這樣的大型數據對象,
LOB 數據對象能夠是二進制數據也能夠是字符數據,其大長度不超過 4G。LOB 數據類
型支持任意訪問方式,LONG 只支持順序訪問方式。LOB 存儲在一個單獨的位置上,同時
一個"LOB 定位符"(LOB locator)存儲在原始的表中,該定位符是一個指向實際數據的指針。
在 PL/SQL 中操做 LOB 數據對象使用 ORACLE 提供的包 DBMS_LOB.LOB 數據類型可分
爲如下四類:
. BFILE
. BLOB
. CLOB
. NCLOB
操做符
與其餘程序設計語言相同,PL/SQL 有一系列操做符。操做符分爲下面幾類: sql
. 算術操做符
. 關係操做符
. 比較操做符
. 邏輯操做符
算術操做符如表 4 所示
operator operation
+ 加
- 減
/ 除
* 乘
** 乘方
關係操做符主要用於條件判斷語句或用於 where 子串中,關係操做符檢查條件和結果
是否爲 true 或 false,表 5 是 PL/SQL 中的關係操做符
operator operation
< 小於操做符
<= 小於或等於操做符
> 大於操做符
>= 大於或等於操做符
= 等於操做符
!= 不等於操做符
<> 不等於操做符
:= 賦值操做符 數據庫
表6 顯示的是比較操做符
operator operation
IS NULL 若是操做數爲 NULL 返回 TRUE
LIKE 比較字符串值
BETWEEN 驗證值是否在範圍以內
IN 驗證操做數在設定的一系列值中
表7.8 顯示的是邏輯操做符
operator operation
AND 兩個條件都必須知足
OR 只要知足兩個條件中的一個
NOT 取反
執行部分
執行部分包含了全部的語句和表達式,執行部分以關鍵字 BEGIN 開始,以關鍵字
EXCEPTION 結束,若是 EXCEPTION 不存在,那麼將以關鍵字 END 結束。分號分隔每一
條語句,使用賦值操做符:=或 SELECT INTO 或 FETCH INTO 給每一個變量賦值,執行部分
的錯誤將在異常處理部分解決,在執行部分中可使用另外一個 PL/SQL 程序塊,這種程序塊
被稱爲嵌套塊
全部的SQL數據操做語句均可以用於執行部分,PL/SQL塊不能再屏幕上顯示SELECT
語句的輸出。SELECT 語句必須包括一個 INTO 子串或者是遊標的一部分,執行部分使用的
變量和常量必須首先在聲明部分聲明,執行部分必須至少包括一條可執行語句,NULL 是一
條合法的可執行語句,事物控制語句 COMMIT 和 ROLLBACK 能夠在執行部分使用,數據
定義語言(Data Definition language)不能在執行部分中使用,DDL 語句與 EXECUTE
IMMEDIATE 一塊兒使用或者是 DBMS_SQL 調用。 express
執行一個 PL/SQL 塊
SQL*PLUS 中匿名的 PL/SQL 塊的執行是在 PL/SQL 塊後輸入/來執行,以下面的例子
所示:
declare v_comm_percent constant number:=10; begin update emp set comm=sal*v_comm_percent where deptno=10; end SQL> / PL/SQL procedure successfully completed.
SQL>
命名的程序與匿名程序的執行不一樣,執行命名的程序塊必須使用 execute 關鍵字:
create or replace procedure update_commission (v_dept in number,v_pervent in number default 10) is begin update emp set comm=sal*v_percent where deptno=v_dept; end
SQL>/
Procedure created
SQL>execute update_commission(10,15);
PL/SQL procedure successfully completed.
SQL> 數組
若是在另外一個命名程序塊或匿名程序塊中執行這個程序,那麼就不須要 EXECUTE 關
進字。
declare v_dept number; begin select a.deptno into v_dept from emp a where job='PRESIDENT' update_commission(v_dept); end SQL>/ PL/SQL procedure successfully completed SQL>
PL/SQL 語言基礎
Oracle PL/SQL 語言基礎(3)
控制結構
控制結構控制 PL/SQL 程序流程的代碼行,PL/SQL 支持條件控制和循環控制結構。
語法和用途
IF..THEN 安全
語法:
IF condition THEN Statements 1; Statements 2; .... END IF
IF 語句判斷條件 condition 是否爲 TRUE,若是是,則執行 THEN 後面的語句,若是
condition 爲 false 或 NULL 則跳過 THEN 到 END IF 之間的語句,執行 END IF 後面的語句。
IF..THEN...ELSE
語法 :
IF condition THEN Statements 1; Statements 2; .... ELSE Statements 1; Statements 2; .... END IF
若是條件 condition 爲 TRUE,則執行 THEN 到 ELSE 之間的語句,不然執行 ELSE 到
END IF 之間的語句。
IF 能夠嵌套,能夠在 IF 或 IF ..ELSE 語句中使用 IF 或 IF..ELSE 語句。
if (a>b) and (a>c) then g:=a;
else g:=b; if c>g then g:=c; end if end if
IF..THEN..ELSIF
語法:
IF condition1 THEN statement1; ELSIF condition2 THEN statement2; ELSIF condition3 THEN statement3; ELSE statement4; END IF; statement5;
若是條件 condition1 爲 TRUE 則執行 statement1,而後執行 statement5,不然判斷
condition2 是否爲 TRUE,若爲 TRUE 則執行 statement2,而後執行 statement5,對於
condition3 也是相同的,若是 condition1,condition2,condition3 都不成立,那麼將執行
statement4,而後執行 statement5。
循環控制
循環控制的基本形式是LOOP語句,LOOP和END LOOP之間的語句將無限次的執行。
LOOP 語句的語法以下:
LOOP
statements;
END LOOP
LOOP 和 END LOOP 之間的語句無限次的執行顯然是不行的,那麼在使用 LOOP 語句
時必須使用 EXIT 語句,強制循環結束,例如:
X:=100; LOOP X:=X+10; IF X>1000 THEN EXIT; END IF END LOOP; Y:=X;
此時Y 的值是 1010.
EXIT WHEN 語句將結束循環,若是條件爲 TRUE,則結束循環。
X:=100; LOOP X:=X+10; EXIT WHEN X>1000; X:=X+10; END LOOP; Y:=X;
WHILE..LOOP
WHILE..LOOP 有一個條件與循環相聯繫,若是條件爲 TRUE,則執行循環體內的語句,
若是結果爲 FALSE,則結束循環。
X:=100; WHILE X<=1000 LOOP X:=X+10; END LOOP; Y=X;
FOR...LOOP
語法:
FOR counter IN [REVERSE] start_range....end_range LOOP statements; END LOOP;
LOOP 和 WHILE 循環的循環次數都是不肯定的,FOR 循環的循環次數是固定的,
counter 是一個隱式聲明的變量,他的初始值是 start_range,第二個值是 start_range+1,直到
end_range,若是start_range 等於end _range,那麼循環將執行一次。若是使用了 REVERSE
關鍵字,那麼範圍將是一個降序。
X:=100; FOR v_counter in 1..10 loop x:=x+10;
end loop y:=x;
若是要退出 for 循環可使用 EXIT 語句。
標籤
用戶可使用標籤使程序得到更好的可讀性。程序塊或循環均可以被標記。標籤的形式
是<>。
標記程序塊
<> [DECLARE] ... ... ... BEGIN ........ [EXCEPTION] ....... END label_name
標記循環
<> LOOP ......... <> loop .......... <> loop ....
EXIT outer_loop WHEN v_condition=0; end loop innermost_loop; .......... END LOOP inner_loop; END LOOP outer_loop;
GOTO 語句
語法:
GOTO LABEL; 服務器
執行GOTO 語句時,控制會當即轉到由標籤標記的語句。PL/SQL 中對 GOTO 語句有
一些限制,對於塊、循環、IF 語句而言,從外層跳轉到內層是非法的。
X :=100; FOR V_COUNTER IN 1..10 LOOP IF V_COUNTER =4 THEN GOTO end_of_loop END IF X:=X+10; <> NULL END LOOP
Y:=X;
注意:NULL 是一個合法的可執行語句。
嵌套
程序塊的內部能夠有另外一個程序塊這種狀況稱爲嵌套。嵌套要注意的是變量,定義在
外部程序塊中的變量能夠在全部子塊中使用,若是在子塊中定義了與外部程序塊變量相同的
變量名,在執行子塊時將使用子塊中定義的變量。子塊中定義的變量不能被父塊引用。一樣
GOTO 語句不能由父塊跳轉道子塊中,反之則是合法的。
《OUTER BLOCK》 DECLARE A_NUMBER INTEGER; B_NUMBER INTEGER; BEGIN --A_NUMBER and B_NUMBER are available here <> DECLARE C_NUMBER INTEGER B_NUMBER NUMBER(20)
BEGIN C_NUMBER:=A_NUMBER; C_NUMBER=OUTER_BLOCK.B_NUMBER; END SUB_BLOCK; END OUT_BLOCK;
小結
咱們在這篇文章中介紹了 PL/SQL 的基礎語法以及如何使用 PL/SQL 語言設計和運行
PL/SQL 程序塊,並將 PL/SQL 程序整合到 Oracle 服務器中,雖然 PL/SQL 程序做爲功能塊
嵌入 Oracle 數據庫中,但 PL/SQL 與 ORACLE 數據庫的緊密結合使得愈來愈多的 Oracle
數據庫管理員和開發人員開始使用 PL/SQL。
複合數據類型
複合數據類型(1)
PL/SQL 有兩種複合數據結構:記錄和集合。記錄由不一樣的域組成,集合由不一樣的元素組成。
在本文中咱們將討論記錄和集合的類型、怎樣定義和使用記錄和集合。
PL/SQL 記錄
記錄是 PL/SQL 的一種複合數據結構,scalar 數據類型和其餘數據類型只是簡單的在包
一級進行預約義,但複合數據類型在使用前必須被定義,記錄之因此被稱爲複合數據類型是
由於他由域這種由數據元素的邏輯組所組成。域能夠是 scalar 數據類型或其餘記錄類型,
它與 c 語言中的結構類似,記錄也能夠當作表中的數據行,域則至關於表中的列,在表和虛
擬表(視圖或查詢)中很是容易定義和使用,行或記錄中的每一列或域均可以被引用或單獨
賦值,也能夠經過一個單獨的語句引用記錄全部的域。在存儲過程或函數中記錄也可能有參
數。
建立記錄
在PL/SQL 中有兩種定義方式:顯式定義和隱式定義。一旦記錄被定義後,聲明或建立
定義類型的記錄變量,而後纔是使用該變量。隱式聲明是在基於表的結構或查詢上使用
%TYPE 屬性,隱式聲明是一個更強有力的工具,這是由於這種數據變量是動態建立的。
顯式定義記錄
顯式定義記錄是在 PL/SQL 程序塊中建立記錄變量以前在聲明部分定義。使用 type 命
令定義記錄,而後在建立該記錄的變量。語法以下:
TYPE record_type IS RECORD (field_definition_list);
field_definition_list 是由逗號分隔的列表。
域定義的語法以下:
field_name data_type_and_size [NOT NULL][{:=|DEFAULT} default_value]
域名必須服從與表或列的命名規則相同的命名規則。下面咱們看一個例子:
DELCARE TYPE stock_quote_rec IS RECORD
(symbol stock.symbol%TYPE ,bid NUMBER(10,4) ,ask NUMBER(10,4) ,volume NUMBER NOT NULL:=0 ,exchange VARCHAR2(6) DEFAULT 'NASDAQ' );
real_time_quote stock_quote_rec; variable
域定義時的%TYPE 屬性用於引用數據庫中的表或視圖的數據類型和大小,而在此以前
程序不知道類型和大小。在上面的例子中記錄域在編譯時將被定義爲與列 SYMBOL 相同的
數據類型和大小,當代碼中要使用來自數據庫中的數據時,在變量或域定義中好使用
%TYPE 來定義。
隱式定義記錄
隱式定義記錄中,咱們不用描述記錄的每個域。這是由於咱們不須要定義記錄的結構,
不須要使用 TYPE 語句,相反在聲明記錄變量時使用%ROWTYPE 命令定義與數據庫表,
視圖,遊標有相同結構的記錄,與 TYPE 命令相同的是它是一種定義得到數據庫數據記錄
的好方法。
DECLARE
accounter_info accounts%ROWTYPR;
CURSOR xactions_cur(acct_no IN VARCHAR2) IS SELECT action,timestamp,holding FROM portfolios WHERE account_nbr='acct_no' ; xaction_info xactions_cur%ROWTYPE; variable 網絡
有一些 PL/SQL 指令在使用隱式定義記錄時沒有使用%ROWTYPE 屬性,好比遊標
FOR 循環或觸發器中的:old 和:new 記錄。
DELCARE
CURSOR xaction_cur IS SELECT action,timeamp,holding FROM portfolios WHERE account_nbr='37' ;
BEGIN FOR xaction_rec in xactions_cur LOOP IF xactions_rec.holding='ORCL' THEN notify_shareholder; END IF; END LOOP;
複合數據類型
複合數據類型(2)
使用記錄
用戶能夠給記錄賦值、將值傳遞給其餘程序。記錄做爲一種複合數據結構意味做他有兩
個層次可用。用戶能夠引用整個記錄,使用 select into 或 fetch 轉移全部域,也能夠將整個
記錄傳遞給一個程序或將全部域的值賦給另外一個記錄。在更低的層次,用戶能夠處理記錄內
單獨的域,用戶能夠給單獨的域賦值或者在單獨的域上運行布爾表達式,也能夠將一個或更
多的域傳遞給另外一個程序。
引用記錄
記錄由域組成,訪問記錄中的域使用點(.)符號。咱們使用上面的例子看看
DELCARE TYPE stock_quote_rec IS RECORD (symbol stock.symbol%TYPE ,bid NUMBER(10,4) ,ask NUMBER(10,4) ,volume NUMBER NOT NULL:=0 ,exchange VARCHAR2(6) DEFAULT 'NASDAQ' );
TYPE detailed_quote_rec IS RECORD (quote stock_quote_rec ,timestamp date ,bid_size NUMBER ,ask.size NUMBER ,last_tick VARCHAR2(4) );
real_time_detail detail_quote_rec;
BEGIN
real_time_detail.bid_size:=1000; real_time_detail.quote.volume:=156700; log_quote(real_time_detail.quote);
給記錄賦值
給記錄或記錄中的域賦值的方法有幾種,可使用 SELECT INTO 或 FETCH 給整個記 錄或單獨的域賦值, 能夠將整個記錄的值賦給其餘記錄,也能夠經過給每一個域賦值來獲得 記錄,如下咱們經過實例講解每一種賦值方法。
一、使用 SELECT INTO
使用SELECT INTO 給記錄賦值要將記錄或域放在 INTO 子串中,INTO 子串中的變量 與 SELECT 中列的位置相對應。 數據結構
例:
DECLARE
stock_info1 stocks%ROWTYPE; stock_info2 stocks%ROWTYPE;
BEGIN
SELECT symbol,exchange INTO stock_info1.symbol,stock_info1.exchange FROM stocks WHERE symbol='ORCL';
SELECT * INTO stock_info2 FROM stocks WHERE symbol='ORCL';
二、使用 FETCH
若是SQL 語句返回多行數據或者但願使用帶參數的遊標,那麼就要使用遊標,這種情 況下使用 FETCH 語句代替 INSTEAD INTO 是一個更簡單、更有效率的方法,但在安全性 較高的包中 FETCH 的語法以下:
FETCH cursor_name INTO variable;
咱們改寫上面的例子:
DECLARE CURSOR stock_cur(symbol_in VARCHAR2) IS SELECT symbol,exchange,begin_date FROM stock WHERE symbol=UPPER(symbol_in);
stock_info stock_cur%ROWTYPE
BEGIN OPEN stock_cur('ORCL'); FETCH stock_cur INTO stock_info;
使用賦值語句將整個記錄複製給另外一個記錄是一項很是有用的技術,不過記錄必須精確
地被聲明爲相同的類型,不能是基於兩個不一樣的 TYPE 語句來得到相同的結構。
例:
DECLARE
TYPE stock_quote_rec IS RECORD (symbol stocks.symbol%TYPE ,bid NUMBER(10,4) ,ask number(10,4) ,volume NUMBER );
TYPE stock_quote_too IS RECORD (symbol stocks.symbol%TYPE ,bid NUMBER(10,4) ,ask number(10,4) ,volume NUMBER ); --這兩個記錄看上去是同樣的,但其實是不同的 stock_one stocks_quote_rec; stock_two stocks_quote_rec; --這兩個域有相同的數據類型和大小
stock_also stock_rec_too;--與 stock_quote_rec 是不一樣的數據類型 BEGIN stock_one.symbol:='orcl'; stock_one.volume:=1234500; stock_two:=stock_one;--正確 syock_also:=stock_one;--錯誤,數據類型錯誤
stock_also.symbol:=stock_one.symbol; stock_also.volume:=stock_one.volume;
記錄不能用於 INSERT 語句和將記錄直接用於比較,下面兩種狀況是錯誤的:
INSERT INTO stocks VALUES (stock_record);
和
IF stock_rec1>stock_rec2 THEN
要特別注意考試中試題中有可能用%ROWTYPE 來欺騙你,但這是錯誤的,記住這一 點。還有可能會出現用記錄排序的狀況,ORACLE 不支持記錄之間的直接比較。對於記錄 比較,能夠採用下面的兩個選擇:
. 設計一個函數,該函數返回 scalar 數據類型,使用這個函數比較記錄,如
IF sort_rec(stock_one)>sort_rec(stock_two) THEN
. 可使用數據庫對象,數據庫對象可使用 order 或 map 方法定義,容許 oracle 對
複合數據類型進行比較。關於數據庫對象的討論已經超越了本文的範圍,要詳細瞭解數據庫 對象,能夠查閱 oracle 手冊。
複合數據類型
複合數據類型(3)
PL/SQL 集合
集合與其餘語言中的數組類似,在 ORACLE7.3 及之前的版本中只有一種集合稱爲
PL/SQL 表,這種類型的集合依然保留,就是索引(INDEX_BY)表,與記錄類似,集合在
定義的時候必須使用 TYPE 語句,而後纔是建立和使用這種類型的變量。
集合的類型
PL/SQL 有三種類型的集合
. Index_by 表
. 嵌套表
. VARRAY
這三種類型的集合之間由許多差別,包括數據綁定、稀疏性(sparsity)、數據庫中的存
儲能力都不相同。綁定涉及到集合中元素數量的限制,VARRAY 集合中的元素的數量是有
限,Index_by 和嵌套表則是沒有限制的。稀疏性描述了集合的下標是否有間隔,Index_by
表老是稀疏的,若是元素被刪除了嵌套表能夠是稀疏的,但 VARRAY 類型的集合則是緊密
的,它的下標之間沒有間隔。
Index_by 表不能存儲在數據庫中,但嵌套表和 VARRAY 能夠被存儲在數據庫中。
雖然這三種類型的集合有不少不一樣之處,但他們也由不少類似的地方:
. 都是一維的相似數組的結構
. 都有內建的方法
. 訪問由點分隔
Index_by 表
Index_by 表集合的定義語法以下:
TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY BINARY_INTERGET;
這裏面重要的關鍵字是 INDEX BY BINARY_INTERGET,沒有這個關鍵字,那麼集合
將是一個嵌套表,element_type能夠是任何合法的PL/SQL數據類型,包括:PLS/INTEGER、
SIGNTYPE、和 BOOLEAN。其餘的集合類型對數據庫的數據類型都有限制,但 Index_by
表不能存儲在數據庫中,因此沒有這些限制。
一旦定義了 index_by 表,就能夠向建立其餘變量那樣建立 index_by 表的變量:
DECLARE TYPE symbol_tab_typ IS TABLE OF VARCHAR2(5) INDEX BY BINARY_INTEGER; symbol_tab symbol_tab_typ; BEGIN
嵌套表
嵌套表很是相似於 Index_by 表,建立的語法也很是類似。使用 TYPE 語句,只是沒有
INDEX BY BINARY_INTEGER 子串。
TYPE type_name IS TABLE OF element_type [NOT NULL]
NOT NULL 選項要求集合全部的元素都要有值,element_type 能夠是一個記錄,可是
這個記錄只能使用標量數據類型字段以及只用於數據庫的數據類型(不能是
PLS_INTEGER,BOOLEAN 或 SIGNTYPE)。
嵌套表和 VARRAY 都能做爲列存儲在數據庫表中,因此集合自身而不是單個的元素可
覺得 NULL,ORACLE 稱這種整個集合爲 NULL 的爲"自動設置爲 NULL(atomically NULL)"
以區別元素爲 NULL 的狀況。當集合爲 NULL 時,即便不會產生異常,用戶也不能引用集
閤中的元素。用戶可使用 IS NULL 操做符檢測集合是否爲 NULL。
存儲在一個數據庫中的嵌套表並不與表中的其它數據存放在同一個數據塊中,它們實際
上被存放在第二個表中。正如沒有 order by 子句 select 語句不能保證返回任何有順序的數
據,從數據庫中取回的嵌套表也不保證元素的順序。因爲集合數據是離線存儲的,對於大型
集合嵌套表是一個不錯的選擇。
VARRAY
VARRAY 或數據變量都有元素的限制。想起他集合同樣 VARRAY 定義仍然使用 TYPE
語句,但關鍵字 VARRAY 或 VARRYING ARRAY 告訴 ORACLE 這是一個 VARRAY 集合。
TYPE type_name IS [VARRAY|VARYING ARRAY] (max_size) OF element_type [NOT NULL]
max_size 是一個整數,用於標示 VARRAY 集合擁有的多元素數目。VARRAY 集合
的元素數量能夠低於 max_size,但不能超過 max_size。element_type 是一維元素的數據類
型,若是 element_type 是記錄,那麼這個記錄只能使用標量數據字段(與嵌套標類似)。
NOT NULL 子串表示集合中的每個元素都必須有值。
與嵌套表類似,VARRAY 可以自動爲 NULL,可使用 IS NULL 操做符進行檢測。與嵌
套表不一樣的是,當 VARRAY 存儲在數據庫中時與表中的其餘數據存放在同一個數據塊中。
正象列的排序保存在表的 SELECT*中同樣元素的順序保存在 VARRAY 中。一樣因爲集合
是在線存儲的,VARRAY 很適合於小型集合。
複合數據類型
複合數據類型(4)
使用集合
象記錄同樣,集合能夠在兩個層面上使用:
. 操做整個集合
. 訪問集合中的單個元素
第一種狀況使用集合名,第二種狀況使用下標:
collection(subscript)
index_by 表的下標是兩爲的整數,能夠爲正也能夠爲負,範圍是: -2147483647--2147483647。嵌套表和 VARRAY 表示元素在集合中的位置,用戶很難靈活 設計下標,這是由於:
. 嵌套表開始是緊密的(相對於疏鬆)
. VARRAY 始終保持緊密
. 這兩種集合的下標都由 1 開始
初始化、刪除、引用集合
使用集合以前必需要初始化,對於 Index_by 表初始化是自動進行的,可是對於嵌套表 和 VARRAY 就必須使用內建的構造函數。若是從新調用,嵌套表和 VARRAY 自動置 NULL, 這不僅是元素置 NULL,而是整個集合置 NULL。給集合內的元素賦值須要使用下標符號。 將一個集合的值賦給另外一個集合,只須要簡單的使用賦值操做符。
Index_by 集合初始化是簡單的,只要涉及其中的一個元素集合就被初始化了。
例:
DECLARE
TYPE symbol_tab_typ IS TABLE OF VARCHAR2(5) INDEX BY BINARY_INTEGER; TYPE account_tab_typ IS TABLE OF account%ROWTYPE INDEX BY BINARY_INTEGER; symbol_tab symbol_tab_typ; account_tab account_tab_typ; new_acct_tab account_tab_typ;
BEGIN --初始化集合元素 147 和-3 SELECT * INTO account_tab(147) FROM accounts WHERE account_nbr=147;
SELECT * INTO account_tab(-3) FROM accounts WHERE account_nbr=3003;
IF account_tab(147).balance<500 THEN chang_maintenance_fee(147); END IF
new_acct_tab:=account_tab; symbol_tab(1):="ORCL"; symbol_tab(2):="CSCO"; symbol_tab(3):="SUNM";
publish_portfolio(symbol_tab);
嵌套表和 VARRAY 由構造函數初始化,構造函數和集合的名字相同,同時有一組參數, 每一個參數對應一個元素,若是參數爲 NULL,那麼對應的元素就被初始化爲 NULL,若是建立 了元素,但沒有填充數據,那麼元素將保持 null 值,能夠被引用,但不能保持數據。若是 元素沒有初始化,那麼就不能引用該元素。
例:
DECLARE
TYPE stock_list IS TABLE OF stock.symbol%TYPE; TYPE top10_list IS VARRAY (10) OF stocks.symbol%TYPE;
biotech_stocks stock_list; tech_10 top10_list;
BEGIN --非法,集合未初始化。 biotech_stocks(1):='AMGN'; IF biotech_stocks IS NULL THEN --初始化集合 biotech_stocks:=('AMGN','BGEN',IMCL','GERN',CRA'); END IF; tech_10:=top10_list('ORCL',CSCO','MSFT','INTC','SUNW','IBM',NULL,NULL); IF tech_10(7) IS NULL THEN tech_10(7):='CPQ'; END tech_10(8):='DELL';
在這個例子中,嵌套表 BIOTECH_STOCKS 初始化有 5 個元素,VARRAY tech_10 集 合多能有 10 個元素,但構造函數只建立了 8 個元素,其中還有兩個元素是 NULL 值,並 程序中給他們賦值。
初始化基於記錄的集合,就必須將記錄傳遞給構造函數,注意不能只是簡單的將記錄的
域傳遞給構造函數。
例:
DECLARE
TYPE stock_quote_rec IS RECORD (symbol stock.symbol%TYPE ,bid NUMBER(10,4) ,ask NUMBER(10,4) ,volume NUMBER NOT NULL:=0 ); TYPE stock_tab_typ IS TABLE OF stock_quote_rec; quote_list stock_tab_typ; single_quote stock_quote_rec;
BEGIN single_quote.symbol:='OPCL'; single_quote.bid:=100; single_quote.ask:=101; single_quote.volume:=25000;
--合法 quote_list:=stock_tab_typ(single_quote); --不合法 quote_list:=stock_tab_typ('CSCO',75,76,3210000); DBMS_OUTPUT.LINE(quote_list(1).bid);
複合數據類型
複合數據類型(5)
集合的方法
除了構造函數外,集合還有不少內建函數,這些函數稱爲方法。調用方法的語法以下:
collection.method
下表中列出 oracle 中集合的方法
方法 描述 使用限制
COUNT 返回集合中元素的個數
DELETE 刪除集合中全部元素
DELETE() 刪除元素下標爲 x 的元素,若是 x 爲 null,則集合保持不變 對 VARRAY 非法
DELETE(,) 刪除元素下標從 X 到 Y 的元素,若是 X>Y 集合保持不變 對 VARRAY 非法
EXIST() 若是集合元素 x 已經初始化,則返回 TRUE, 不然返回 FALSE
EXTEND 在集合末尾添加一個元素 對 Index_by 非法
EXTEND() 在集合末尾添加 x 個元素 對 Index_by 非法
EXTEND(,) 在集合末尾添加元素 n 的 x 個副本 對 Index_by 非法
FIRST 返回集合中的第一個元素的下標號,對於 VARRAY 集合始終返回 1。
LAST 返回集合中後一個元素的下標號, 對於 VARRAY 返回值始終等於 COUNT.
LIMIT
返回 VARRY 集合的大的元素個數,對於嵌套表和對於嵌套表和 Index_by 爲 null
Index_by 集合無用
NEXT()
返回在元素 x 以後及緊挨着它的元素的值,若是該元素是後一個元素,則返回 null.
PRIOR()
返回集合中在元素 x 以前緊挨着它的元素的值,若是該元素是第一個元素,則返 回 null。
TRI M 從集合末端開始刪除一個元素
對於 index_by 不合 法
TRIM() 從集合末端開始刪除 x 個元素 對 index_by 不合法
關於集合之間的比較
集合不能直接用於比較,要比較兩個集合,能夠設計一個函數,該函數返回一個標量數 據類型。
IF stock_list1>stock_list2 ----非法 IF sort_collection(stock_list1)>sort_collection(stock_list2) THEN --合法
但能夠比較在集合內的兩個元素。
單行函數和組函數
單行函數和組函數詳解(1)
函數是一種有零個或多個參數而且有一個返回值的程序。在 SQL 中 Oracle 內建了一系列函
數,這些函數均可被稱爲 SQL 或 PL/SQL 語句,函數主要分爲兩大類:
單行函數
組函數
本文將討論如何利用單行函數以及使用規則。
SQL 中的單行函數
SQL 和 PL/SQL 中自帶不少類型的函數,有字符、數字、日期、轉換、和混合型等多
種函數用於處理單行數據,所以這些均可被統稱爲單行函數。這些函數都可用於
SELECT,WHERE、ORDER BY 等子句中,例以下面的例子中就包含了
TO_CHAR,UPPER,SOUNDEX 等單行函數。
SELECT ename,TO_CHAR(hiredate,'day,DD-Mon-YYYY') FROM emp Where UPPER(ename) Like 'AL%' ORDER BY SOUNDEX(ename)
單行函數也能夠在其餘語句中使用,如 update 的 SET 子句,INSERT 的 VALUES 子
句,DELET 的 WHERE 子句,認證考試特別注意在 SELECT 語句中使用這些函數,因此我
們的注意力也集中在 SELECT 語句中。
NULL 和單行函數
在如何理解 NULL 上開始是很困難的,就算是一個頗有經驗的人依然對此感到困惑。
NULL 值表示一個未知數據或者一個空值,算術操做符的任何一個操做數爲 NULL 值,結果
均爲提個 NULL 值,這個規則也適合不少函數,只有
CONCAT,DECODE,DUMP,NVL,REPLACE 在調用了 NULL 參數時可以返回非 NULL 值。
在這些中 NVL 函數時重要的,由於他能直接處理 NULL 值,NVL 有兩個參數:
NVL(x1,x2),x1 和 x2 都式表達式,當 x1 爲 null 時返回 X2,不然返回 x1。
下面咱們看看 emp 數據表它包含了薪水、獎金兩項,須要計算總的補償
column name emp_id salary bonus
key type pk nulls/unique nn,u nn fk table datatype number number number length 11.2 11.2
不是簡單的將薪水和獎金加起來就能夠了,若是某一行是 null 值那麼結果就將是 null,
好比下面的例子:
update emp set salary=(salary+bonus)*1.1
這個語句中,僱員的工資和獎金都將更新爲一個新的值,可是若是沒有獎金,即 salary
+ null,那麼就會得出錯誤的結論,這個時候就要使用 nvl 函數來排除 null 值的影響。
因此正確的語句是:
update emp set salary=(salary+nvl(bonus,0)*1.1
單行函數和組函數
單行函數和組函數詳解(2)
單行字符串函數
單行字符串函數用於操做字符串數據,他們大多數有一個或多個參數,其中絕大多數返
回字符串
ASCII()
c1 是一字符串,返回 c1 第一個字母的 ASCII 碼,他的逆函數是 CHR()
SELECT ASCII('A') BIG_A,ASCII('z') BIG_z FROM emp
BIG_A BIG_z 65 122
CHR(<i>)[NCHAR_CS]
i 是一個數字,函數返回十進制表示的字符
select CHR(65),CHR(122),CHR(223) FROM emp
CHR65 CHR122 CHR223 A z B
CONCAT(,)
c1,c2 均爲字符串,函數將 c2 鏈接到 c1 的後面,若是 c1 爲 null,將返回 c2.若是 c2 爲
null,則返回 c1,若是 c一、c2 都爲 null,則返回 null。他和操做符||返回的結果相同
select concat('slobo ','Svoboda') username from dual
username
slobo Syoboda
INITCAP()
c1 爲一字符串。函數將每一個單詞的第一個字母大寫其它字母小寫返回。單詞由空格,
控制字符,標點符號限制。
select INITCAP('veni,vedi,vici') Ceasar from dual
Ceasar
Veni,Vedi,Vici
INSTR(,[,<i>[,]])
c1,c2 均爲字符串,i,j 爲整數。函數返回 c2 在 c1 中第 j 次出現的位置,搜索從 c1 的第
i 個字符開始。當沒有發現須要的字符時返回 0,若是 i 爲負數,那麼搜索將從右到左進行,
可是位置的計算仍是從左到右,i 和 j 的缺省值爲 1.
select INSTR('Mississippi','i',3,3) from dual
INSTR('MISSISSIPPI','I',3,3)
11
select INSTR('Mississippi','i',-2,3) from dual
INSTR('MISSISSIPPI','I',3,3)
2
INSTRB(,[,i[,j])
與INSTR()函數同樣,只是他返回的是字節,對於單字節 INSTRB()等於 INSTR()
LENGTH()
c1 爲字符串,返回 c1 的長度,若是 c1 爲 null,那麼將返回 null 值。
select LENGTH('Ipso Facto') ergo from dual
ergo
10
LENGTHb()
與LENGTH()同樣,返回字節。
lower()
返回c 的小寫字符,常常出如今 where 子串中
select LOWER(colorname) from itemdetail WHERE LOWER(colorname) LIKE '%white%'
COLORNAME
Winterwhite
LPAD(,<i>[,])
c1,c2 均爲字符串, i 爲整數。在 c1 的左側用 c2 字符串補足致長度 i,可屢次重複,若是
i 小於 c1 的長度,那麼只返回 i 那麼長的 c1 字符,其餘的將被截去。c2 的缺省值爲單空格,
參見 RPAD。
select LPAD(answer,7,'') padded,answer unpadded from question;
PADDED UNPADDED
Yes Yes NO NO Maybe maybe
LTRIM(,)
把c1 中左邊的字符去掉,使其第一個字符不在 c2 中,若是沒有 c2,那麼 c1 就不會
改變。
select LTRIM('Mississippi','Mis') from dual
LTR
ppi
RPAD(,<i>[,])
在c1 的右側用 c2 字符串補足致長度 i,可屢次重複,若是 i 小於 c1 的長度,那麼只返
回 i 那麼長的 c1 字符,其餘的將被截去。c2 的缺省值爲單空格,其餘與 LPAD 類似
RTRIM(,)
把c1 中右邊的字符去掉,使其第後一個字符不在 c2 中,若是沒有 c2,那麼 c1 就不
會改變。
REPLACE(,[,])
c1,c2,c3 都是字符串,函數用 c3 代替出如今 c1 中的 c2 後返回。
select REPLACE('uptown','up','down') from dual
REPLACE
downtown
STBSTR(,<i>[,])
c1 爲一字符串,i,j 爲整數,從 c1 的第 i 位開始返回長度爲 j 的子字符串,若是 j 爲空,
則直到串的尾部。
select SUBSTR('Message',1,4) from dual
SUBS
Mess
SUBSTRB(,<i>[,])
與SUBSTR 大體相同,只是 I,J 是以字節計算。
SOUNDEX()
返回與 c1 發音類似的詞
select SOUNDEX('dawes') Dawes SOUNDEX('daws') Daws, SOUNDEX('dawson') from dual
Dawes Daws Dawson
D200 D200 D250
TRANSLATE(,,)
將c1 中與 c2 相同的字符以 c3 代替
select TRANSLATE('fumble','uf','ar') test from dual
TEXT
ramble
TRIM([[]] from c3)
將c3 串中的第一個,後一個,或者都刪除。
select TRIM(' space padded ') trim from dual
TRIM
space padded
UPPER()
返回c1 的大寫,常出現 where 子串中
select name from dual where UPPER(name) LIKE 'KI%'
NAME
KING
單行函數和組函數
單行函數和組函數詳解(3)
單行數字函數
單行數字函數操做數字數據,執行數學和算術運算。全部函數都有數字參數並返回數字
值。全部三角函數的操做數和值都是弧度而不是角度,oracle 沒有提供內建的弧度和角度的 轉換函數。
ABS() 返回n 的絕對值
ACOS() 反餘玄函數,返回-1 到 1 之間的數。n 表示弧度
select ACOS(-1) pi,ACOS(1) ZERO FROM dual
PI ZERO
3.14159265 0
ASIN() 反正玄函數,返回-1 到 1,n 表示弧度
ATAN() 反正切函數,返回 n 的反正切值,n 表示弧度。
CEIL() 返回大於或等於 n 的小整數。
COS() 返回n 的餘玄值,n 爲弧度
COSH() 返回n 的雙曲餘玄值,n 爲數字。
select COSH(<1.4>) FROM dual
COSH(1.4)
2.15089847
EXP() 返回e 的 n 次冪,e=2.71828183.
FLOOR() 返回小於等於 N 的大整數。
LN() 返回N 的天然對數,N 必須大於 0
LOG(,) 返回以 n1 爲底 n2 的對數
MOD() 返回n1 除以 n2 的餘數,
POWER(,) 返回n1 的 n2 次方
ROUND(,) 返回舍入小數點右邊 n2 位的 n1 的值,n2 的缺省值爲 0,這回將小數點接近的整數, 若是 n2 爲負數就舍入到小數點左邊相應的位上,n2 必須是整數。
select ROUND(12345,-2),ROUND(12345.54321,2) FROM dual
ROUND(12345,-2) ROUND(12345.54321,2)
12300 12345.54
SIGN() 若是n 爲負數,返回-1,若是 n 爲正數,返回 1,若是 n=0 返回 0.
SIN() 返回n 的正玄值,n 爲弧度。
SINH() 返回n 的雙曲正玄值,n 爲弧度。
SQRT() 返回n 的平方根,n 爲弧度
TAN() 返回n 的正切值,n 爲弧度
TANH() 返回n 的雙曲正切值,n 爲弧度
TRUNC(,) 返回截尾到 n2 位小數的 n1 的值,n2 缺省設置爲 0,當 n2 爲缺省設置時會將 n1 截尾 爲整數,若是 n2 爲負值,就截尾在小數點左邊相應的位上。
單行日期函數
單行日期函數操做 DATA 數據類型,絕大多數都有 DATA 數據類型的參數,絕大多數 返回的也是 DATA 數據類型的值。
ADD_MONTHS(,<i>) 返回日期 d 加上 i 個月後的結果。 i 可使任意整數。若是 i 是一個小數,那麼數據庫將 隱式的他轉換成整數,將會截去小數點後面的部分。
LAST_DAY()
函數返回包含日期 d 的月份的後一天
MONTHS_BETWEEN(,) 返回d1 和 d2 之間月的數目,若是 d1 和 d2 的日的日期都相同,或者都使該月的後一 天,那麼將返回一個整數,不然會返回的結果將包含一個分數。
NEW_TIME(,,) d1 是一個日期數據類型,當時區 tz1 中的日期和時間是 d 時,返回時區 tz2 中的日期 和時間。tz1 和 tz2 時字符串。
NEXT_DAY(,) 返回日期 d 後由 dow 給出的條件的第一天,dow 使用當前會話中給出的語言指定了一 週中的某一天,返回的時間份量與 d 的時間份量相同。
select NEXT_DAY('01-Jan-2000','Monday') "1st Monday",NEXT_DAY('01-Nov-2004','Tuesday')+7 "2nd Tuesday") from dual;
1st Monday 2nd Tuesday
03-Jan-2000 09-Nov-2004
ROUND([,])
將日期 d 按照 fmt 指定的格式舍入,fmt 爲字符串。
SYADATE
函數沒有參數,返回當前日期和時間。
TRUNC([,])
返回由 fmt 指定的單位的日期 d.
單行函數和組函數
單行函數和組函數詳解(4)
單行轉換函數
單行轉換函數用於操做多數據類型,在數據類型之間進行轉換。
CHARTORWID() c 使一個字符串,函數將 c 轉換爲 RWID 數據類型。
SELECT test_id from test_case where rowid=CHARTORWID('AAAA0SAACAAAALiAAA')
CONVERT(,[,]) c 尾字符串,dset、sset 是兩個字符集,函數將字符串 c 由 sset 字符集轉換爲 dset 字 符集,sset 的缺省設置爲數據庫的字符集。
HEXTORAW() x 爲 16 進制的字符串,函數將 16 進制的 x 轉換爲 RAW 數據類型。
RAWTOHEX() x 是 RAW 數據類型字符串,函數將 RAW 數據類轉換爲 16 進制的數據類型。
ROWIDTOCHAR() 函數將 ROWID 數據類型轉換爲 CHAR 數據類型。
TO_CHAR([[,) x 是一個 data 或 number 數據類型,函數將 x 轉換成 fmt 指定格式的 char 數據類型, 若是 x 爲日期 nlsparm=NLS_DATE_LANGUAGE 控制返回的月份和日份所使用的語言。 若是 x 爲數字 nlsparm=NLS_NUMERIC_CHARACTERS 用來指定小數位和千分位的分隔 符,以及貨幣符號。
NLS_NUMERIC_CHARACTERS ="dg", NLS_CURRENCY="string"
TO_DATE([,[,)
c 表示字符串,fmt 表示一種特殊格式的字符串。返回按照 fmt 格式顯示的 c,nlsparm 表示使用的語言。函數將字符串 c 轉換成 date 數據類型。
TO_MULTI_BYTE() c 表示一個字符串,函數將 c 的擔子截字符轉換成多字節字符。
TO_NUMBER([,[,) c 表示字符串,fmt 表示一個特殊格式的字符串,函數返回值按照 fmt 指定的格式顯示。 nlsparm 表示語言,函數將返回 c 表明的數字。
TO_SINGLE_BYTE() 將字符串 c 中得多字節字符轉化成等價的單字節字符。該函數僅當數據庫字符集同時包 含單字節和多字節字符時才使用
其它單行函數
BFILENAME( ,) dir 是一個 directory 類型的對象,file 爲一文件名。函數返回一個空的 BFILE 位 置值指示符,函數用於初始化 BFILE 變量或者是 BFILE 列。
DECODE(,,[,,,[]) x 是一個表達式,m1 是一個匹配表達式,x 與 m1 比較,若是 m1 等於 x,那 麼返回 r1,不然,x 與 m2 比較,依次類推 m3,m4,m5....直到有返回結果。
DUMP(,[,[,[,]]]) x 是一個表達式或字符,fmt 表示 8 進制、10 進制、16 進制、或則單字符。函 數返回包含了有關 x 的內部表示信息的 VARCHAR2 類型的值。若是指定了 n1,n2 那麼從 n1 開始的長度爲 n2 的字節將被返回。
EMPTY_BLOB() 該函數沒有參數,函數返回 一個空的 BLOB 位置指示符。函數用於初始化一 個 BLOB 變量或 BLOB 列。
EMPTY_CLOB()
該函數沒有參數,函數返回 一個空的 CLOB 位置指示符。函數用於初始化一 個 CLOB 變量或 CLOB 列。
GREATEST() exp_list 是一列表達式,返回其中大的表達式,每一個表達式都被隱含的轉換
第一個表達式的數據類型,若是第一個表達式是字符串數據類型中的任何一個,那
麼返回的結果是 varchar2 數據類型, 同時使用的比較是非填充空格類型的比較。
LEAST() exp_list 是一列表達式,返回其中小的表達式,每一個表達式都被隱含的轉換
第一個表達式的數據類型,若是第一個表達式是字符串數據類型中的任何一個,將
返回的結果是 varchar2 數據類型, 同時使用的比較是非填充空格類型的比較。
UID 該函數沒有參數,返回惟一標示當前數據庫用戶的整數。
USER 返回當前用戶的用戶名
USERENV() 基於opt 返回包含當前會話信息。opt 的可選值爲:
ISDBA 會話中SYSDBA 腳色響應,返回 TRUE SESSIONID 返回審計會話標示符 ENTRYID 返回可用的審計項標示符 INSTANCE 在會話鏈接後,返回實例標示符。該值只用於運行 Parallel 服 務器而且有 多個實例的狀況下使用。 LANGUAGE 返回語言、地域、數據庫設置的字符集。 LANG 返回語言名稱的 ISO 縮寫。 TERMINAL 爲當前會話使用的終端或計算機返回操做系統的標示符。
VSIZE() x 是一個表達式。返回 x 內部表示的字節數。
單行函數和組函數
單行函數和組函數詳解(5)
SQL 中的組函數
組函數也叫集合函數,返回基於多個行的單一結果,行的準確數量沒法肯定,除非查詢
被執行而且全部的結果都被包含在內。與單行函數不一樣的是,在解析時全部的行都是已知的。
因爲這種差異使組函數與單行函數有在要求和行爲上有微小的差別.
組(多行)函數
與單行函數相比,oracle 提供了豐富的基於組的,多行的函數。這些函數能夠在 select
或 select 的 having 子句中使用,當用於 select 子串時經常都和 GROUP BY 一塊兒使用。
AVG([{DISYINCT|ALL}])
返回數值的平均值。缺省設置爲 ALL.
SELECT AVG(sal),AVG(ALL sal),AVG(DISTINCT sal) FROM scott.emp
AVG(SAL) AVG(ALL SAL) AVG(DISTINCT SAL)
1877.94118 1877.94118 1916.071413
COUNT({*|DISTINCT|ALL} )
返回查詢中行的數目,缺省設置是 ALL,*表示返回全部的行。
MAX([{DISTINCT|ALL}])
返回選擇列表項目的大值,若是 x 是字符串數據類型,他返回一個 VARCHAR2 數據
類型,若是 X 是一個 DATA 數據類型,返回一個日期,若是 X 是 numeric 數據類型,返回
一個數字。注意 distinct 和 all 不起做用,應爲大值與這兩種設置是相同的。
MIN([{DISTINCT|ALL}])
返回選擇列表項目的小值。
STDDEV([{DISTINCT|ALL}])
返回選者的列表項目的標準差,所謂標準差是方差的平方根。
SUM([{DISTINCT|ALL}])
返回選擇列表項目的數值的總和。
VARIANCE([{DISTINCT|ALL}])
返回選擇列表項目的統計方差。
用 GROUP BY 給數據分組
正如題目暗示的那樣組函數就是操做那些已經分好組的數據,咱們告訴數據庫用
GROUP BY 怎樣給數據分組或者分類,當咱們在 SELECT 語句的 SELECT 子句中使用組
函數時,咱們必須把爲分組或很是數列放置在 GROUP BY 子句中,若是沒有用 group by
進行專門處理,那麼缺省的分類是將整個結果設爲一類。
select stat,counter(*) zip_count from zip_codes GROUP BY state;
ST ZIP_COUNT -- --------- AK 360 AL 1212 AR 1309 AZ 768 CA 3982
在這個例子中,咱們用 state 字段分類;若是咱們要將結果按照 zip_codes 排序,能夠用
ORDER BY 語句,ORDER BY 子句可使用列或組函數。
select stat,counter(*) zip_count from zip_codes GROUP BY state ORDER BY COUNT(*) DESC;
ST COUNT(*) -- -------- NY 4312 PA 4297 TX 4123 CA 3982
用 HAVING 子句限制分組數據
如今你已經知道了在查詢的 SELECT 語句和 ORDER BY 子句中使用主函數,組函數
只能用於兩個子串中,組函數不能用於 WHERE 子串中,例以下面的查詢是錯誤的 :
錯誤 SELECT sales_clerk,SUN(sale_amount) FROM gross_sales WHERE sales_dept='OUTSIDE' AND SUM(sale_amount)>10000 GROUP BY sales_clerk
這個語句中數據庫不知道 SUM()是什麼,當咱們須要指示數據庫對行分組,而後限制
分組後的行的輸出時,正確的方法是使用 HAVING 語句:
SELECT sales_clerk,SUN(sale_amount)
FROM gross_sales WHERE sales_dept='OUTSIDE' GROUP BY sales_clerk HAVING SUM(sale_amount)>10000;
嵌套函數
函數能夠嵌套。一個函數的輸出能夠是另外一個函數的輸入。操做數有一個可繼承的執行
過程。但函數的優先權只是基於位置,函數遵循由內到外,由左到右的原則。嵌套技術通常
用於象 DECODE 這樣的能被用於邏輯判斷語句 IF....THEN...ELSE 的函數。
嵌套函數能夠包括在組函數中嵌套單行函數,或者組函數嵌套入單行函數或組函數中。
好比下面的例子:
SELECT deptno, GREATEST(COUNT(DISTINCT job),COUNT(DISTINCT mgr) cnt, COUNT(DISTINCT job) jobs, COUNT(DISTINCT mgr) mgrs FROM emp GROUP BY deptno;
DEPTNO CNT JOBS MGRS ------ --- ---- ---- 10 4 4 2 20 4 3 4 30 3 3 2
表和視圖
表和視圖(1)
Oracle 數據庫數據對象中基本的是表和視圖,其餘還有約束、序列、函數、存儲過程、
包、觸發器等。對數據庫的操做能夠基本歸結爲對數據對象的操做,理解和掌握 Oracle 數據
庫對象是學習 Oracle 的捷徑。
表和視圖
Oracle 中表是數據存儲的基本結構。ORACLE8 引入了分區表和對象表,ORACLE8i
引入了臨時表,使表的功能更強大。視圖是一個或多個表中數據的邏輯表達式。本文咱們將
討論怎樣建立和管理簡單的表和視圖。
管理表
表能夠看做有行和列的電子數據表,表是關係數據庫中一種擁有數據的結構。用
CREATE TABLE 語句創建表,在創建表的同時,必須定義表名,列,以及列的數據類型和
大小。例如:
CREATE TABLE products ( PROD_ID NUMBER(4), PROD_NAME VAECHAR2(20), STOCK_QTY NUMBER(5,3) );
這樣咱們就創建了一個名爲 products 的表, 關鍵詞 CREATE TABLE 後緊跟的表名,
而後定義了三列,同時規定了列的數據類型和大小。
在建立表的同時你能夠規定表的完整性約束,也能夠規定列的完整性約束,在列上普通
的約束是 NOT NULL,關於約束的討論咱們在之後進行。
在創建或更改表時,能夠給表一個缺省值。缺省值是在增長行時,增長的數據行中某一
項值爲 null 時,oracle 即認爲該值爲缺省值。
下列數據字典視圖提供表和表的列的信息:
. DBA_TABLES
. DBA_ALL_TABLES
. USER_TABLES
. USER_ALL_TABLES
. ALL_TABLES
. ALL_ALL_TABLES
. DBA_TAB_COLUMNS
. USER_TAB_COLUMNS
. ALL_TAB_COLUMNS
表的命名規則
表名標識一個表,因此應儘量在表名中描述表,oracle 中表名或列名長能夠達 30
個字符串。表名應該以字母開始,能夠在表名中包含數字、下劃線、#、$等。
從其它表中創建表
可使用查詢從基於一個或多個表中創建表,表的列的數據類型和大小有查詢結果決
定。創建這種形式的表的查詢能夠選擇其餘表中全部的列或者只選擇部分列。在 CREATE
TABLE 語句中使用關鍵字 AS,例如:
SQL>CREATE TABLE emp AS SELECT * FROM employee
TABLE CREATED
SQL> CREATE TABLE Y AS SELECT * FROM X WHERE no=2
須要注意的是若是查詢涉及 LONG 數據類型,那麼 CREATE TABLE....AS SELECT....
將不會工做。
更改表定義
在創建表後,有時候咱們可能須要修改表,好比更改列的定義,更改缺省值,增長新列,
刪除列等等。ORACLE 使用 ALTER TABLE 語句來更改表的定義
一、增長列
語法:
ALTER TABLE [schema.] table_name ADD column_definition
例:
ALTER TABLE orders ADD order_date DATE;
TABLE ALTER
對於已經存在的數據行,新列的值將是 NULL.
二、更改列
語法:
ALTER TABLE [schema.] table_name MODIFY column_name new_attributes;
例:
ALTER TABLE orders MODITY (quantity number(10,3),status varchar2(15));
這個例子中咱們修改了表 orders,將 STATUS 列的長度增長到 15,將 QUANTITY 列減
小到 10,3;
修改列的規則以下:
. 能夠增長字符串數據類型的列的長度,數字數據類型列的精度。
. 減小列的長度時,該列應該不包含任何值,全部數據行都爲 NULL.
. 改變數據類型時,該列的值必須是 NULL.
. 對於十進制數字,能夠增長或減小但不能下降他的精度。
三、刪除數據列
優化ORACLE 數據庫,惟一的方法是刪除列,從新創建數據庫。在 ORACLE8i 中有很
多方法刪除列,你能夠刪除未用數據列或者能夠標示該列爲未用數據列而後刪除。
刪除數據列的語法是:
ALTER TABLE [schema.] table_name DROP {COLUM column_names | (column_names)}[CASCADE CONSTRAINS]
要注意的是在刪除列時關於該列的索引和完整性約束也同時刪除。注意關鍵字
CASCADE CONSTRAINS,若是刪除的列是多列約束的一部分,那麼這個約束條件相對於
其餘列也同時刪除。
若是用戶擔憂在大型數據庫中刪除列要花太多時間,能夠先將他們標記爲未用數據列,
標記未用數據列的語法以下:
ALTER TABLE [schema.] table_name SET UNUSED {COLUM column_names | (column_names)}[CASCADE CONSTRAINS]
這個語句將一個或多個數據列標記爲未用數據列,但並不刪除數據列中的數據,也不釋
放佔用的磁盤空間。可是,未用數據列在視圖和數據字典中並不顯示,而且該數據列的名稱
將被刪除,新的數據列可使用這個名稱。基於該數據列的索引、約束,統計等都將被刪除。
刪除未用數據列的語句是:
ALTER TABLE [schema.] table_name DROP {UNUSED COLUM | COLUMN CONTINUE}
表和視圖
表和視圖(2)
刪除表和更改表名
刪除表很是簡單,但它是一個不可逆轉的行爲。
語法:
DROP TABLE [schema.] table_name [CASCADE CONSTRAINTS]
刪除表後,表上的索引、觸發器、權限、完整性約束也同時刪除。ORACLE 不能刪除 視圖,或其餘程序單元,但 oracle 將標示他們無效。若是刪除的表涉及引用主鍵或惟一關 鍵字的完整性約束時,那麼 DROP TABLE 語句就必須包含 CASCADE CONSTRAINTS 子 串。
更改表名
RENAME 命令用於給表和其餘數據庫對象更名。ORACLE 系統自動將基於舊錶的完整 性約束、索引、權限轉移到新表中。ORACLE 同時使全部基於舊錶的數據庫對象,好比視 圖、程序、函數等,爲不合法。
語法:
RENAME old_name TO new_name;
例:
SQL> RENAME orders TO purchase_orders;
TABLE RENAMED
截短表
TRUNCATE 命令與 DROP 命令類似, 但他不是刪除整個數據表,因此索引、完整性
約束、觸發器、權限等都不會被刪除。缺省狀況下將釋放部分表和視圖空間,若是用戶不希
望釋放表空間,TRUNCATE 語句中要包含 REUSE STORAGE 子串。TRUNCATE 命令語 法以下:
TRUNCATE {TABLE|CLUSTER} [schema.] name {DROP|REUSE STORAGE}
例:
SQL> TRUNCATE TABLE t1;
TABLE truncate.
管理視圖
視圖是一個或多個表中的數據的簡化描述,用戶能夠將視圖當作一個存儲查詢(stored query)或一個虛擬表(virtual table).查詢僅僅存儲在 oracle 數據字典中,實際的數據沒有存
放在任何其它地方,因此創建視圖不用消耗其餘的空間。視圖也能夠隱藏複雜查詢,好比多
表查詢,但用戶只能看見視圖。視圖能夠有與他所基於表的列名不一樣的列名。用戶能夠創建
限制其餘用戶訪問的視圖。
創建視圖
CREATE VIEW 命令建立視圖,定義視圖的查詢能夠創建在一個或多個表,或其餘視 圖上。查詢不能有 FOR UPDATE 子串,在早期的 ORACLE8i 版本中不支持 ORDER BY 子串,如今的版本中 CREATE VIEW 能夠擁有 ORDER BY 子串。
例:
SQL> CREATE VIEW TOP_EMP AS SELECT empno EMPLOYEE_ID,ename EMPLOYEE_NAME,salary FROM emp WHERE salary >2000
用戶能夠在建立視圖的同時更改列名,方法是在視圖名後當即加上要命名的列名。從新
定義視圖須要包含 OR REPLACE 子串。
SQL> CREATE VIEW TOP_EMP (EMPLOYEE_ID,EMPLOYEE_NAME,SALARY) AS
SELECT empno ,ename ,salary FROM emp WHERE salary >2000
若是在建立的視圖包含錯誤在正常狀況下,視圖將不會被建立。但若是你須要建立一個
帶錯誤的視圖必須在 CREATE VIEW 語句中帶上 FORCE 選項。如:
CREATE FORCE VIEW ORDER_STATUS AS SELECT * FROM PURCHASE_ORDERS WHERE STATUS='APPPOVE';
SQL>/
warning :View create with compilation errors
這樣將建立了一個名爲 ORDER_STATUS 的視圖,但這樣的視圖的狀態是不合法的, 若是之後狀態發生變化則能夠從新編譯,其狀態也變成合法的。
從視圖中得到數據
從視圖中得到數據與從表中得到數據基本同樣,用戶能夠在鏈接和子查詢中使用視圖,
也可使用 SQL 函數,以及全部 SELECT 語句的字串。
插入、更新、刪除數據
用戶在必定的限制條件下能夠經過視圖更新、插入、刪除數據。若是視圖鏈接多個表,
那麼在一個時間裏只能更新一個表。全部的能被更新的列能夠在數據字典
USER_UPDATETABLE_COLUMNS 中查到。
用戶在 CREATE VIEW 中可使用了 WITH 子串。WITH READ ONLY 子串表示建立 的視圖是一個只讀視圖,不能進行更新、插入、刪除操做。WITH CHECK OPTION 表示可 以進行插入和更新操做,但應該知足 WHERE 子串的條件。這個條件就是建立視圖 WHERE 子句的條件,好比在上面的例子中用戶建立了一個視圖 TOP_EMP,在這個視圖中用戶不能 插入 salary 小於 2000 的數據行。
刪除視圖
刪除視圖使用 DROP VIEW 命令。同時將視圖定義從數據字典中刪除,基於視圖的權 限也同時被刪除,其餘涉及到該視圖的函數、視圖、程序等都將被視爲非法。
例:
DROP VIEW TOP_EMP;
完整性約束
完整性約束(1)
完整性約束
完整性約束用於加強數據的完整性,Oracle 提供了 5 種完整性約束:
Check
NOT NULL
Unique
Primary
Foreign key
完整性約束是一種規則,不佔用任何數據庫空間。完整性約束存在數據字典中,在執行
SQL 或 PL/SQL 期間使用。用戶能夠指明約束是啓用的仍是禁用的,當約束啓用時,他增
強了數據的完整性,不然,則反之,但約束始終存在於數據字典中。
禁用約束,使用 ALTER 語句
ALTER TABLE table_name DISABLE CONSTRAINT constraint_name;
或
ALTER TABLE policies DISABLE CONSTRAINT chk_gender
若是要從新啓用約束:
ALTER TABLE policies ENABLE CONSTRAINT chk_gender
刪除約束
ALTER TABLE table_name DROP CONSTRAINT constraint_name
或
ALTER TABLE policies DROP CONSTRAINT chk_gender;
Check 約束
在數據列上 Check 約束須要 一個特殊的布爾條件或者將數據列設置成 TRUE,至少
一個數據列的值是 NULL,Check 約束用於加強表中數據內容的簡單的商業規則。用戶使用
Check 約束保證數據規則的一致性。Check 約束能夠涉及該行同屬 Check 約束的其餘數據
列但不能涉及其餘行或其餘表,或調用函數 SYSDATE,UID,USER,USERENV。若是用戶
的商業規則須要這類的數據檢查,那麼可使用觸發器。Check 約束不保護 LOB 數據類型
的數據列和對象、嵌套表、VARRY、ref 等。單一數據列能夠有多個 Check 約束保護,一
個 Check 約束能夠保護多個數據列。
建立表的 Check 約束使用 CREATE TABLE 語句,更改表的約束使用 ALTER TABLE
語句。
語法:
CONSTRAINT [constraint_name] CHECK (condition);
Check 約束能夠被建立或增長爲一個表約束,當 Check 約束保護多個數據列時,必須
使用表約束語法。約束名是可選的而且若是這個名字不存在,那麼 oracle 將產生一個以
SYS_開始的惟一的名字。
例:
CREATE TABLE policies (policy_id NUMBER, holder_name VARCHAR2(40), gender VARCHAR2(1) constraint chk_gender CHECK (gender in ('M','F'), marital_status VARCHAR2(1), date_of_birth DATE, constraint chk_marital CHECK (marital_status in('S','M','D','W')) );
NOT NULL 約束
NOT NULL 約束應用在單一的數據列上,而且他保護的數據列必需要有數據值。缺省
情況下,ORACLE 容許任何列均可以有 NULL 值。某些商業規則要求某數據列必需要有值,
NOT NULL 約束將確保該列的全部數據行都有值。
例:
CREATE TABLE policies (policy_id NUMBER, holder_name VARCHAR2(40) NOT NULL, gender VARCHAR2(1), marital_status VARCHAR2(1), date_of_birth DATE NOT NULL );
對於NOT NULL 的 ALTER TABLE 語句與其餘約束稍微有點不一樣。
ALTER TABLE policies MODIFY holder_name NOT NULL
完整性約束
完整性約束(2)
惟一性約束(Unique constraint)
惟一性約束能夠保護表中多個數據列,保證在保護的數據列中任何兩行的數據都不相
同。惟一性約束與表一塊兒建立,在惟一性約束建立後,可使用 ALTER TABLE 語句修改。
語法:
column_name data_type CONSTRAINT constraint_name UNIQUE
若是惟一性約束保護多個數據列,那麼惟一性約束要做爲表約束增長。語法以下:
CONSTRAINT constraint_name (column) UNIQUE USING INDEX TABLESPACE (tablespace_name) STORAGE (stored clause)
惟一性約束由一個 B-tree 索引加強,因此能夠在 USING 子串中爲索引使用特殊特徵,
好比表空間或存儲參數。CREATE TABLE 語句在建立惟一性約束的同時也給目標數據列建
立了一個惟一的索引。
CREATE TABLE insured_autos (policy_id NUMBER CONSTRAINT pk_policies PRIMARY KEY, vin VARCHAR2(10), coverage_begin DATE, coverage_term NUMBER, CONSTRAIN unique_auto UNIQUE (policy_id,vin) USING INDEX TABLESPACE index STORAGE (INITIAL 1M NEXT 10M PCTINCREASE 0) );
用戶能夠禁用未以性約束,但他仍然存在,禁用惟一性約束使用 ALTER TABLE 語句
ALTER TABLE insured_autos DISABLE CONSTRAIN unique_name;
刪除惟一性約束,使用 ALTER TABLE....DROP CONSTRAIN 語句
ALTER TABLE insured_autos DROP CONSTRAIN unique_name;
注意用戶不能刪除在有外部鍵指向的表的惟一性約束。這種狀況下用戶必須首先禁用或
刪除外部鍵(foreign key)。
刪除或禁用惟一性約束一般同時刪除相關聯的惟一索引,於是下降了數據庫性能。常常
刪除或禁用惟一性約束有可能致使丟失索引帶來的性能錯誤。要避免這樣錯誤,能夠採起下
面的步驟:
一、在惟一性約束保護的數據列上建立非惟一性索引。
二、添加惟一性約束
主鍵(Primary Key)約束
表有惟一的主鍵約束。表的主鍵能夠保護一個或多個列,主鍵約束可與 NOT NULL 約
束共同做用於每一數據列。NOT NULL 約束和惟一性約束的組合將保證主鍵惟一地標識每
一行。像惟一性約束同樣,主鍵由 B-tree 索引加強。
建立主鍵約束使用 CREATE TABLE 語句與表一塊兒建立,若是表已經建立了,可使用
ALTER TABLE 語句。
CREATE TABLE policies (policy_id NUMBER CONSTRAINT pk_policies PRIMARY KEY, holder_name VARCHAR2(40), gender VARCHAR2(1), marital_status VARCHAR2(1), date_of_birth DATE );
與惟一性約束同樣,若是主鍵約束保護多個數據列,那麼必須做爲一個表約束建立。
CREATE TABLE insured_autos (policy_id NUMBER, vin VARCHAR2(40), coverage_begin DATE, coverage_term NUMBER, CONSTRAINT pk_insured_autos PRIMARY KEY (policy_id,vin) USING INDEX TABLESPACE index STORAGE (INITIAL 1M NEXT 10M PCTINCREASE 0) );
禁用或刪除主鍵必須與 ALTER TABLE 語句一塊兒使用
ALTER TABLE policies DROP PRIMARY KEY;
或
ALTER TABLE policies DISABLE PRIMARY KEY;
外部鍵約束(Foreign key constraint)
外部鍵約束保護一個或多個數據列,保證每一個數據行的數據包含一個或多個 null 值,
或者在保護的數據列上同時擁有主鍵約束或惟一性約束。引用(主鍵或惟一性約束)約束可
以保護同一個表,也能夠保護不一樣的表。與主鍵和惟一性約束不一樣外部鍵不會隱式創建一個
B-tree 索引。在處理外部鍵時,咱們經常使用術語父表(parent table)和子表(child table),
父表表示被引用主鍵或惟一性約束的表,子表表示引用主鍵和惟一性約束的表。
建立外部鍵使用 CREATE TABLE 語句,若是表已經創建了,那麼使用 ALTER TABLE
語句。
CREATE TABLE insured_autos (policy_id NUMBER CONSTRAINT policy_fk REFERENCE policies(policy_id ON DELETE CASCADE, vin VARCHAR2(40), coverage_begin DATE, coverage_term NUMBER, make VARCHAR2(30), model VARCHAR(30), year NUMBER, CONSTRAIN auto_fk FROEIGN KEY (make,model,year) REFERENCES automobiles (make,model,year)
ON DELETE SET NULL );
ON DELETE 子串告訴 ORACLE 若是父紀錄(parent record)被刪除後,子記錄作什麼。
缺省狀況下禁止在子記錄還存在的狀況下刪除父紀錄。
外部鍵和 NULL 值
在外部鍵約束保護的數據列中 NULL 值的處理可能產生不可預料的結果。ORACLE 使
用 ISO standar Match None 規則加強外部鍵約束。這個規則規定若是任何外部鍵做用的數
據列包含有一個 NULL 值,那麼任何保留該鍵的數據列在父表中沒有匹配值。
好比,在父表 AUTOMOBILES 中,主鍵做用於數據列 MAKE,MODEL,YEAR 上,
用戶使用的表 INSURED_AUTOS 有一個外部約束指向 AOTOMOBILES,注意在
INSURES_AUTOS中有一數據行的MODEL列爲NULL值,這一行數據已經經過約束檢查,
即便 MAKE 列也沒有顯示在父表 AUTOMOBILES 中,以下表:
表1 AUTOMOBILES
MAKE MODEL YEAR
Ford Taurus 2000
Toyota Camry 1999
表2 INSURED_AUTOS
POLICY_ID MAKE MODEL YEAR
576 Ford Taurus 2000
577 Toyota Camry 1999
578 Tucker NULL 1949
延遲約束檢驗(Deferred Constraint Checking)
約束檢驗分兩種狀況,一種是在每一條語句結束後檢驗數據是否知足約束條件,這種檢
驗稱爲當即約束檢驗(immediately checking),另外一種是在事務處理完成以後對數據進行檢
驗稱之爲延遲約束檢驗。在缺省狀況下 Oracle 約束檢驗是當即檢驗(immediately checking),
若是不知足約束將先是一條錯誤信息,但用戶能夠經過 SET CONSTRAINT 語句選擇延遲
約束檢驗。語法以下:
SET CONSTRAINT constraint_name|ALL DEFEERRED|IMMEDIATE --;
完整性約束
完整性約束(3)
序列(Sequences)
Oracle 序列是一個連續的數字生成器。序列經常使用於人爲的關鍵字,或給數據行排序否
則數據行是無序的。像約束同樣,序列只存在於數據字典中。序列號能夠被設置爲上升、下
降,能夠沒有限制或重複使用直到一個限制值。建立序列使用 SET SEQUENCE 語句。
CREATE SEQUENCE [schema] sequence KEYWORD
KEYWORD 包括下面的值:
KEYWORD 描述
START WITH 定義序列生成的第一個數字,缺省爲 1
INCREMENT BY
定義序列號是上升仍是降低,對於一個降序的序列 INCREMENT BY 爲負值
MINVALUE
定義序列能夠生成的小值,這是降序序列中的限制值。缺省狀況下該值爲 NOMINVALUE,NOMINVALUE,對於升序爲 1,對於降序爲-10E26.
MAXVALUE
序列能生成的大數字。這是升序序列中的限制值,缺省的 MAXVALUE 爲 NOMAXVALUE,NOMAXVALUE,對於升序爲 10E26,對於降序爲-1。
CYCLE 設置序列值在達到限制值之後能夠重複
NOCYCLE
設置序列值在達到限制值之後不能重複,這是缺省設置。當試圖產生 MAXVALUE+1 的值時,將 會產生一個異常
CACHE 定義序列值佔據的內存塊的大小,缺省值爲 20
NOCACHE
在每次序列號產生時強制數據字典更新,保證在序列值之間沒有間隔當建立序列時,START WITH 值必須等於或大於 MINVALUE。
刪除序列使用 DROP SEQUENCE 語句
DROP SEQUENCE sequence_name
索引(INDEXES)
索引是一種能夠提升查詢性能的數據結構,在這一部分咱們將討論索引如何提升查詢性
能的。ORACLE 提供瞭如下幾種索引:
B-Tree、哈希(hash)、位圖(bitmap)等索引類型 基於原始表的索引 基於函數的索引 域(Domain)索引
實際應用中主要是 B-Tree 索引和位圖索引,因此咱們將集中討論這兩種索引類型。
B-Tree 索引
B-Tree 索引是普通的索引,缺省條件下創建的索引就是這種類型的索引。B-Tree 索 引能夠是惟一或非惟一的,能夠是單一的(基於一列)或鏈接的(多列)。B-Tree 索引在
檢索高基數數據列(高基數數據列是指該列有不少不一樣的值)時提供了好的性能。對於取
出較小的數據 B-Tree 索引比全表檢索提供了更有效的方法。但當檢查的範圍超過表的 10% 時就不能提升取回數據的性能。正如名字所暗示的那樣,B-Tree 索引是基於二元樹的,由 枝幹塊(branch block)和樹葉塊(leaf block)組成,枝幹塊包含了索引列(關鍵字)和另外一索
引的地址。樹葉塊包含了關鍵字和給表中每一個匹配行的 ROWID。
位圖索引
位圖索引主要用於決策支持系統或靜態數據,不支持行級鎖定。位圖索引能夠是簡單的
(單列)也能夠是鏈接的(多列),但在實踐中絕大多數是簡單的。位圖索引好用於低到
中羣集(cardinality)列,在這些列上多位圖索引能夠與 AND 或 OR 操做符結合使用。位圖 索引使用位圖做爲鍵值,對於表中的每一數據行位圖包含了 TRUE(1)、FALSE(0)、 或 NULL 值。位圖索引的位圖存放在 B-Tree 結構的頁節點中。B-Tree 結構使查找位圖很是 方便和快速。另外,位圖以一種壓縮格式存放,所以佔用的磁盤空間比 B-Tree 索引要小得 多。
同義詞(Synonyms)
對另外一個數據對象而言同義詞是一個別名。public 同義詞是針對全部用戶的,相對而言 private 同義詞則只針對對象擁有者或被授予權限的帳戶。在本地數據庫中同義詞能夠表示
表、視圖、序列、程序、函數或包等數據對象,也能夠經過連接表示另外一個數據庫的對象。
建立同義詞語法以下:
CREATE [PUBLIC] SYNONYM synonym_name FOR [schema.] object[@db_link];
例:
CREATE PUBLIC SYNONYM policies FOR poladm.policies@prod;
CREATE SYNONYM plan_table FOR system.plan_table;
過程和函數
過程和函數(1)
過程和函數
過程和函數都以編譯後的形式存放在數據庫中,函數能夠沒有參數也能夠有多個參數並
有一個返回值。過程有零個或多個參數,沒有返回值。函數和過程均可以經過參數列表接收
或返回零個或多個值,函數和過程的主要區別不在於返回值,而在於他們的調用方式。過程
是做爲一個獨立執行語句調用的:
pay_involume(invoice_nbr,30,due_date);
函數以合法的表達式的方式調用:
order_volumn:=open_orders(SYSDATE,30);
建立過程的語法以下:
CREATE [ OR REPLACE] PROCEDURE [schema.]procedure_name [parameter_lister] {AS|IS} declaration_section BEGIN executable_section [EXCEPTION exception_section] END [procedure_name]
每一個參數的語法以下:
paramter_name mode datatype [(:=|DEFAULT) value]
mode 有三種形式:IN、OUT、INOUT。
IN 表示在調用過程的時候,實際參數的取值被傳遞給該過程,形式參數被認爲是隻讀
的,當過程結束時,控制會返回控制環境,實際參數的值不會改變。
OUT 在調用過程時實際參數的取值都將被忽略,在過程內部形式參數只能是被賦值,
而不能從中讀取數據,在過程結束後形式參數的內容將被賦予實際參數。
INOUT 這種模式是 IN 和 OUT 的組合;在過程內部實際參數的值會傳遞給形式參數,
形勢參數的值可讀也可寫,過程結束後,形勢參數的值將賦予實際參數。
建立函數的語法和過程的語法基本相同,惟一的區別在於函數有 RETUREN 子句
CREATE [ OR REPLACE] FINCTION [schema.]function_name [parameter_list] RETURN returning_datatype {AS|IS} declaration_section BEGIN executable_section [EXCEPTION] exception_section END [procedure_name]
在執行部分函數必須有喲個或多個 return 語句。
在建立函數中能夠調用單行函數和組函數,例如:
CREATE OR REPLACE FUNCTION my_sin(DegreesIn IN NUMBER) RETURN NUMBER IS
pi NUMBER=ACOS(-1); RadiansPerDegree NUMBER;
BEGIN RadiansPerDegree=pi/180; RETURN(SIN(DegreesIn*RadiansPerDegree)); END
過程和函數
過程和函數(2)
包
包是一種將過程、函數和數據結構捆綁在一塊兒的容器;包由兩個部分組成:外部可視包
規範,包括函數頭,過程頭,和外部可視數據結構;另外一部分是包主體(package body),包 主體包含了全部被捆綁的過程和函數的聲明、執行、異常處理部分。
打包的 PL/SQL 程序和沒有打包的有很大的差別,包數據在用戶的整個會話期間都一直
存在,當用戶得到包的執行受權時,就等於得到包規範中的全部程序和數據結構的權限。但
不能只對包中的某一個函數或過程進行受權。包能夠重載過程和函數,在包內能夠用同一個
名字聲明多個程序,在運行時根據參數的數目和數據類型調用正確的程序。
建立包必須首先建立包規範,建立包規範的語法以下:
CREATE [OR REPLACE] PACKAGE package_name {AS|IS} public_variable_declarations | public_type_declarations | public_exception_declarations | public_cursor_declarations | function_declarations | procedure_specifications END [package_name]
建立包主體使用 CREATE PACKAGE BODY 語句:
CREATE [OR REPLACE] PACKAGE BODY package_name {AS|IS} private_variable_declarations | private_type_declarations | private_exception_declarations | private_cursor_declarations | function_declarations | procedure_specifications END [package_name]
私有數據結構是那些在包主體內部,對被調用程序而言是不可見的。
觸發器(Triggers)
觸發器是一種自動執行響應數據庫變化的程序。能夠設置爲在觸發器事件以前或以後觸
發或執行。可以觸發觸發器事件的事件包括下面幾種:
DML 事件 DDL 事件 數據庫事件
DML 事件觸發器能夠是語句或行級觸發器。DML 語句觸發器在觸發語句以前或以後觸 發 DML 行級觸發器在語句影響的行變化以前或以後觸發。用戶能夠給單一事件和類型定義
多個觸發器,但沒有任何方法能夠加強多觸發器觸發的命令。下表列出了用戶能夠利用的觸
發器事件:
事件 觸發器描述
INSERT 當向表或視圖插入一行時觸發觸發器
UPDATE 更新表或視圖中的某一行時觸發觸發器
DELETE 從表或視圖中刪除某一行時觸發觸發器
CREATE 當使用 CREATE 語句爲數據庫或項目增長一個對象時觸發觸發器
ALTER 當使用 ALTER 語句爲更改一個數據庫或項目的對象時觸發觸發器
DROP 當使用 DROP 語句刪除一個數據庫或項目的對象時觸發觸發器
START 打開數據庫時觸發觸發器,在事件後觸發
SHUTDOWN 關閉數據庫時觸發,事件前觸發
LOGON 當一個會話創建時觸發,事件前觸發
LOGOFF 當關閉會話時觸發,事件前觸發
SERVER 服務器錯誤發生時觸發觸發器,事件後觸發
建立觸發器的語法以下:
CREATE [OR REPLACE] TRIGGER trigger_name {before|after|instead of} event ON {table_or_view_name|DATABASE} [FOR EACH ROW[WHEN condition]] trigger_body
只有DML 觸發器(INSERT、UPDATE、DELETE)語句可使用 INSTEAD OF 觸發 器而且只有表的 DML 觸發器能夠是 BEFORE 或 AFTER 觸發器。
象約束同樣觸發器能夠被設置爲禁用或啓用來關閉或打開他們的執行體(EXECUTE), 將觸發器設置爲禁用或啓用使用 ALTER TRIGGER 語句:
ALTER TRIGGER trigger_name ENABLE; ALTER TRIGGER trigger_name DISABLE;
要禁用或啓用表的全部觸發器,使用 ALTER TABLE 語句
ALTER TRIGGER table_name DISABLE ALL TRIGGER; ALTER TRIGGER table_name ENABLE ALL TRIGGER;
刪除觸發器使用 DROP TRIGGER
DROP TRIGGER trigger_name;
數據字典
Oracle 數據字典包含了用戶數據庫的元數據。帶下劃線的表名稱中帶 OBJ$、UET$、 SOURCE$,這些表是在執行 CREATE DATABASE 語句期間由 sql.bsq 腳本建立的,通常 狀況下用戶不多訪問這些表。腳本 catalog.sql(一般位於$oracle_home/rdbms/admin)在 CREATE DATABASE 語句以後當即運行,建立數據字典視圖。
數據字典視圖大體能夠分爲三類:
.前綴爲 USER_的數據字典視圖,包含了用戶擁有的對象的信息。
.前綴爲 ALL_的數據字典視圖,包含了用戶當前能夠訪問的所有對象和權限的信息。
.前綴爲 DBA_的數據字典視圖,包含了數據庫擁有的全部對象和權限的信息。
在絕大多數數據字典視圖中都有象 DBA_TABLES,ALL_TABLES 和 USER_TABLES 這樣的視圖家族。Oracle 中有超過 100 個視圖家族,因此要全面介紹這些視圖家族是單調
乏味的並且沒有多大的意義。在下表中列出了重要和經常使用的視圖家族,須要注意的是每
個視圖家族都有一個 DBA_,一個 ALL_一個 USER_視圖。
視圖家族(View Family) 描述
COL_PRIVS 包含了表的列權限,包括授予者、被授予者和權限
EXTENTS 數據範圍信息,好比數據文件,數據段名(segment_name)和大小
INDEXES 索引信息,好比類型、惟一性和被涉及的表
IND_COLUMNS 索引列信息,好比索引上的列的排序方式
OBJECTS 對象信息,好比狀態和 DDL time
ROLE_PRIVS 角色權限,好比 GRANT 和 ADMIN 選項
SEGMENTS 表和索引的數據段信息,好比 tablespace 和 storage
SEQUECNCES 序列信息,好比序列的 cache、cycle 和 ast_number
SOURCE 除觸發器以外的全部內置過程、函數、包的源代碼
SYNONYMS 別名信息,好比引用的對象和數據庫連接 db_link
SYS_PRIVS 系統權限,好比 grantee、privilege、admin 選項
TAB_COLUMNS 表和視圖的列信息,包括列的數據類型
TAB_PRIVS 表權限,好比授予者、被授予者和權限
TABLES 表信息,好比表空間(tablespace),存儲參數(storage parms)和數據行的數量
TRIGGERS 觸發器信息,好比類型、事件、觸發體(trigger body)
USERS 用戶信息,好比臨時的和缺省的表空間
VIEWS 視圖信息,包括視圖定義
在Oracle 中還有一些不經常使用的數據字典表,但這些表不是真正的字典家族,他們都是 一些重要的單一的視圖。
VIEW NAME 描述
USER_COL_PRIVS_MADE 用戶授予他人的列權限
USER_COL_PRIVS_RECD 用戶得到的列權限
USER_TAB_PRIVS_MADE 用戶授予他人的表權限
USER_TAB_PRIVS_RECD 用戶得到的表權限
其餘的字典視圖中主要的是 V$視圖,之因此這樣叫是由於他們都是以 V$或 GV$開頭 的。V$視圖是基於 X$虛擬視圖的。V$視圖是 SYS 用戶所擁有的,在缺省情況下,只有 SYS 用戶和擁有 DBA 系統權限的用戶能夠看到全部的視圖,沒有 DBA 權限的用戶能夠看到 USER_和 ALL_視圖,但不能看到 DBA_視圖。與 DBA_,ALL,和 USER_視圖中面向數據庫 信息相反,這些視圖可視的給出了面向實例的信息。
在大型系統上化幾周時間手工輸入每一條語句
手工輸入帶用戶名變量的語句,而後再輸入每個用戶名,這須要花好幾個小時的時
間
寫一條SQL 語句,生成須要的 ALTER USER 語句,而後執行他,這隻須要幾分鐘 時間
很明顯咱們將選擇生成 SQL 的方法:
例:
SELECT 'ALTER USER'||username|| 'TEMPORARY TABLESPACE temp;' FROM DBA_USERS WHERE username<>'SYS' AND temporary_tablespace<>'TEMP';
這個查詢的結果將被脫機處理到一個文件中,而後在執行:
ALTER USER SYSTEM TEMPORARY TABLESPACE temp; ALTER USER OUTLN TEMPORARY TABLESPACE temp; ALTER USER DBSNMP TEMPORARY TABLESPACE temp; ALTER USER SCOTT TEMPORARY TABLESPACE temp; ALTER USER DEMO TEMPORARY TABLESPACE temp;
操做和控制語言
數據操做和控制語言詳解(1)
SQL 語言共分爲四大類:數據查詢語言 DQL,數據操縱語言 DML, 數據定義語言 DDL,
數據控制語言 DCL。其中用於定義數據的結構,好比 建立、修改或者刪除數據庫;DCL
用於定義數據庫用戶的權限;在這篇文章中我將詳細講述這兩種語言在 Oracle 中的使用方
法。
DML 語言
DML 是 SQL 的一個子集,主要用於修改數據,下表列出了 ORACLE 支持的 DML 語
句。
語句 用途 INSERT 向表中添加行 UPDATE 更新存儲在表中的數據 DELETE 刪除行 SELECT FOR UPDATE 禁止其餘用戶訪問 DML 語句正在處理的行。 LOCK TABLE 禁止其餘用戶在表中使用 DML 語句
插入數據
INSERT 語句經常用於向表中插入行,行中能夠有特殊數據字段,或者能夠用子查詢從
已存在的數據中創建新行。
列目錄是可選的,缺省的列的目錄是全部的列名,包括 comlumn_id,comlumn_id 能夠
在數據字典視圖 ALL_TAB_COLUMNS,USER_TAB_COLUMNS,或者
DBA_TAB_COLUMNS 中找到。
插入行的數據的數量和數據類型必須和列的數量和數據類型相匹配。不符合列定義的數
據類型將對插入值實行隱式數據轉換。NULL 字符串將一個 NULL 值插入適當的列中。關鍵
字 NULL 經常用於表示將某列定義爲 NULL 值。
下面的兩個例子是等價的。
INSERT INTO customers(cust_id,state,post_code) VALUE('Ariel',NULL,'94501');
或
INSERT INTO customers(cust_id,state,post_code) VALUE('Ariel',,'94501');
更新數據
UPDATE 命令用於修改表中的數據。
UPDATE order_rollup SET(qty,price)=(SELECT SUM(qty),SUM(price) FROM order_lines WHERE customer_id='KOHL' WHERE cust_id='KOHL' AND order_period=TO_DATE('01-Oct-2000')
刪除數據
DELETE 語句用來從表中刪除一行或多行數據,該命令包含兩個語句:
一、關鍵字 DELETE FROM 後跟準備從中刪除數據的表名。
二、WHERE 後跟刪除條件
DELETE FROM po_lines WHERE ship_to_state IN ('TX','NY','IL') AND order_date<TRUNC(SYSTEM)-90< td>
清空表
若是你想刪除表中全部數據,清空表,能夠考慮使用 DDL 語言的 TRUNCATE 語句。
TRUNCATE就像沒有WHERE子句的DELETE命令同樣。TRUNCATE將刪除表中全部行。
TRUNCATE 不是 DML 語句是 DDL 語句,他和 DELETE 右不一樣的特色。
TRUNCATE TABLE (schema)table DROP(REUSE) STORAGE
STORAGE 子串是可選的,缺省是 DROP STORAGE。當使用 DROP STORAGE 時將
縮短表和表索引,將表收縮到小範圍,並從新設置 NEXT 參數。REUSE STORAGE 不會
縮短表或者調整 NEXT 參數。
TRUNCATE 和 DELETE 有如下幾點區別
一、TRUNCATE 在各類表上不管是大的仍是小的都很是快。若是有 ROLLBACK 命令
DELETE 將被撤銷,而 TRUNCATE 則不會被撤銷。
二、TRUNCATE 是一個 DDL 語言,向其餘全部的 DDL 語言同樣,他將被隱式提交,
不能對 TRUNCATE 使用 ROLLBACK 命令。
三、TRUNCATE 將從新設置高水平線和全部的索引。在對整個表和索引進行徹底瀏覽
時,通過 TRUNCATE 操做後的表比 DELETE 操做後的表要快得多。
四、TRUNCATE 不能觸發任何 DELETE 觸發器。
五、不能授予任何人清空他人的表的權限。
六、當表被清空後表和表的索引講從新設置成初始大小,而 delete 則不能。
七、不能清空父表。
SELECT FOR UPDATE
select for update 語句用於鎖定行,阻止其餘用戶在該行上修改數據。當該行被鎖定後
其餘用戶能夠用 SELECT 語句查詢該行的數據,但不能修改或鎖定該行。
鎖定表
LOCK 語句經常用於鎖定整個表。當表被鎖定後,大多數 DML 語言不能在該表上使用。
LOCK 語法以下:
LOCK schema table IN lock_mode
其中lock_mode 有兩個選項:
share 共享方式
exclusive 惟一方式
例:
LOCK TABLE intentory IN EXCLUSIVE MODE
死鎖
當兩個事務都被鎖定,而且互相都在等待另外一個被解鎖,這種狀況稱爲死鎖。
當出現死鎖時,ORACLE 將檢測死鎖條件,並返回一個異常。
操做和控制語言
數據操做和控制語言詳解(2)
事務控制
事務控制包括協調對相同數據的多個同步的訪問。當一個用戶改變了另外一個用戶正在使
用的數據時,oracle 使用事務控制誰能夠操做數據。
事務
事務表示工做的一個基本單元,是一系列做爲一個單元被成功或不成功操做的 SQL 語 句。在 SQL 和 PL/SQL 中有不少語句讓程序員控制事務。程序員能夠:
一、顯式開始一個事物,選擇語句級一致性或事務級一致性
二、設置撤銷回滾點,並回滾到回滾點
三、完成事務永遠改變數據或者放棄修改。
事務控制語句
語句 用途 Commit 完成事務,數據修改爲功並對其餘用戶開放 Rollback 撤銷事務,撤銷全部操做 rollback to savepoint 撤銷在設置的回滾點之後的操做 set transaction 響應事務或語句的一致性;特別對於事務使用回滾段
例:
BEGIN UPDATE checking SET balance=balance-5000 WHERE account='Kieesha';
INSERT INTO checking_log(action_date,action,amount) VALUES (SYSDATE,'Transfer to brokerage',-5000);
UPDATE brokerage SET cash_balance=cash_balance+5000 WHERE account='Kiesha';
INSERT INTO brokerage_log(action_date,action,amount) VALUES (SYSDATE,'Tracfer from checking',5000)
COMMIT
EXCEPTION WHEN OTHERS ROLLBACK
END
Savepoint 和 部分回滾(Partial Rollback)
在SQL 和 PL/SQL 中 Savepoint 是在一事務範圍內的中間標誌。常常用於將一個長的
事務劃分爲小的部分。保留點 Savepoint 可標誌長事務中的任何點,容許可回滾該點以後的 操做。在應用程序中常用 Savepoint;例如一過程包含幾個函數,在每一個函數前可創建 一個保留點,若是函數失敗,很容易返回到每個函數開始的狀況。在回滾到一個 Savepoint 以後,該 Savepoint 以後所得到的數據封鎖被釋放。爲了實現部分回滾能夠用帶 TO Savepoint 子句的 ROLLBACK 語句將事務回滾到指定的位置。
例
BEGIN
INSERT INTO ATM_LOG(who,when,what,where) VALUES ('Kiesha',SYSDATE,'Withdrawal of $100','ATM54') SAVEPOINT ATM_LOGGED;
UPDATE checking SET balance=balance-100 RETURN balance INTO new_balance;
IF new_balance<0 THEN ROLLBACK TO ATM_LOGGED; COMMIT RAISE insufficient_funda; END IF
END
關鍵字 SAVEPOINT 是可選的,因此下面兩個語句是等價的:
ROLLBACK TO ATM_LOGGED; ROLLBACK TO SAVEPOINT ATM_LOGGED;
一致性和事務
一致性是事物控制的關鍵慨念。掌握了 oracle 的一致性模型,能使您更好的,更恰當 的使用事務控制。oracle 經過一致性保證數據只有在事務所有完成後才能被用戶看見和使 用。這項技術對多用戶數據庫有巨大的做用。
oracle 經常使用語句級(state-level)一致性,保證數據在語句的生命期之間是可見的但 不能被改變。事務由多個語句組成,當使用事務時,事物級(transaction-level)一致性在整
個事務生命期中保證數據對全部語句都是可見的。
oracle 經過 SCN(syatem change number)實施一致性。一個 SCN 是一個面向時間的 數據庫內部鍵。SCN 只會增長不會減小,SCN 表示了時間上的一個點,每一個數據塊都有一 個 SCN,經過比較這個點實施操做。
事務級一致性
SET TRANSACTION 的一個做用是確保事務級一致或語句級一致中有一個實施。 ORACLE 使用這些術語:
ISOLATION LEVEL READ COMMIT 表示語句級一致
ISOLATION LEVEL SERIALIZABLE 表示事務級一致。
例:
SET TRANSACTION ISOLATION LEVEL READ COMMIT;
SET TRANSACTION ISOLATION LEVEL READ COMMIT
下面的語句也能確保事務級一致:
SET TRANSCATION READ ONLY
任何企圖在只讀(READ ONLY)事務中修改數據的操做都會拋出一個異常。可是,READ ONLY 事務只能在下列語句中使用:
SELECT(沒有 FOR UPDATE 子句) LOCK TABLE SET ROLE ALTER SYSTEM ALTER ALARM
即便沒有改變任何數據,READ ONLY 事務依然必須使用一個 COMMIT 或 ROLLBACK 以結束整個事務。
SET TRANSCTION 的另一個應用是在回滾時直接使用回滾段(ROLLBACK
SEGMENT)。回滾段是 ORACLE 的一個特殊的數據對象,回滾段的頭部包含正在使用該 回滾段事務的信息。當用戶回滾事務(ROLLBACK)時,ORACLE 將會利用回滾段中的數 據前影像來將修改的數據恢復到原來的值。oracle 用 round-robin 給事務隨機分配回滾段。
一個大的事務能夠分配任何回滾段,這也許會致使回滾段的大小變得很大。所以要避免讓大
的事務隨機分配回滾段。
事務以 SET TRANSACTION 開始,象下面這樣:
SET TRANSACTION USE ROLLBACK SEGMENT rb_large;
rb_large 是一個大的回滾段的名稱,如今就給一個大的事務分配了一個大的回滾段,其 他的小的回滾段將不禁動態空間管理,這樣就更有效率。
下面咱們看一個例子.咱們有一個回滾段表空間大小是 2G,在高峯時期須要 10 個回滾 段以知足用戶的須要,這些高峯在線用戶只有小的事務。一週咱們連續運行了 4 個大的事 務,這些事務須要刪除和加載數據,每個撤銷須要 1G,回滾段的大小以下:
rb_large(initial 100M minextenta 2)
rb1 (initial 1M next minextents 5) rb2 (initial 1M next minextents 5) rb3 (initial 1M next minextents 5) rb4 (initial 1M next minextents 5) rb5 (initial 1M next minextents 5) rb6 (initial 1M next minextents 5) rb7 (initial 1M next minextents 5) rb8 (initial 1M next minextents 5) rb9 (initial 1M next minextents 5) rb10 (initial 1M next minextents 5)
全部的都很是恰當的安排在 2G 的表空間中,若是咱們缺省的 round-robin 給事務分配
回滾段, 4 個大事務將有 4 個獨立的回滾段,每一個回滾段的大小將是 1G,若是這樣咱們的 2G 表空間就不夠,而數據庫管理員就不得不在夜晚 2 點起來工做,每一個事務都由如下面的語 句開始:
SET TRANSACTION USE ROLLBACK SEGMENT rb_large
如今 4個事務重用相同的表空間,保正 4 個回滾段的表空間在 2G 之內。數據庫管理
員能夠睡到天亮。
操做和控制語言
數據操做和控制語言詳解(3)
創建和修改用戶
CREATE USER 語句將創建一個用戶。當一個用戶鏈接到 ORACLE 數據庫時,它必 須被驗證。ORACLE 中驗證有三種類型:
Database
external
Global
缺省是數據庫驗證,當用戶鏈接到數據庫時,oracle 將檢測用戶是不是數據庫的合法用 戶,而且要提供正確的 password.external 驗證,oracle 將只檢測用戶是不是合法用戶, password 已經被網絡或系統驗證了。global 驗證也是隻檢測是不是合法用戶,password 由 oraclesecurity server 驗證。
Database 驗證用戶帳號
數據庫驗證帳號是張好的缺省類型,也是普通的類型。創建一個帳號是 piyush,口令 是 welcome 的帳號,只需執行下面的命令:
CREATE USE piyush IDENTIFIED BY welcome
piyush 能夠經過下面的語句將口令改變爲 saraswatt:
ALTER USER piyush IDENTIFIED BY saraswati;
外部驗證用戶帳號
用戶帳號進入數據庫時能夠不提供口令,這種狀況下代替數據庫識別口令的是客戶端操
做系統。外部驗證帳號有時也叫 OPS$帳號,當他們初在 oracle6 開始介紹時,oracle 帳 號都有關鍵字前綴OPS$,這也就是爲何init.ora 參數os_authent_prefix是OPS$--默認特 徵與 oracle6 保持一致。os_authent_prefix 定義的字符串必須被預處理爲用於 Oracle 外部 識別帳號的操做系統帳號名。建立操做系統用戶 appl 的語句是:
CREATE USER ops$appl IDENTIFIED EATERNALLY
但在一般狀況下,os_authent_prefix 將被設置爲空,像下面這樣:
CREATE USER appl IDENTIFIED EATERNALLY
這樣效果是同樣的,關鍵字IDENTIFIED EXTERNALLY 告訴ORACLE 這是一個外部識 別帳號。
GLOBAL 用戶帳號
GLOBAL 類型的用戶帳號數據庫不檢測口令,而是由 X.509 目錄服務器檢測口令。創 建一個 GLOBAL 類型的用戶帳號的方法是:
CREATE USER scott IDENTIFIED GLOBALLY AS "CN=scott,OU=divisional,O=sybex,C=US"
關鍵字 IDENTIFIED GLOBALLY AS 表示創建的是一個 GLOBAL 類型的用戶帳號.
建立和更改用戶帳號
CREATE USER 用於創建用戶帳號和給用戶帳號的屬性賦值。ALTER USER 用於更 改用戶帳號和屬性。但 CREATE USER 語句必須包括用戶名和口令。
有部分屬性能用 CREATER USER 和 ALTER USER 語句設置,下面對是這些的屬性
具體描述:
給用戶分配缺省表空間
表空間(tablespace)是放置表、索引、叢等用戶對象的。若是在 create user 語句中沒 有包含表空間,那麼缺省的是系統表空間。
CREATE USER piyush IDENTIFIED BY saraswati DEFAULTE TABLESPACE user_data; ALTER USER manoj DEFAULTE TABLESPACE dev1_data;
給用戶分配臨時表空間
臨時表空間,顧名思義是臨時存放表、索引等用戶對象的臨時段。創建方法同樣
CREATE USER piyush IDENTIFIED BY saraswati Temporary TABLESPACE user_data; ALTER USER manoj Temporary TABLESPACE dev1_data;
給用戶分配表空間的使用定額
使用定額限制用戶在表空間中使用磁盤的數量。定額能夠按字節、千字節、兆字節或者
無限制來制定。
CREATE USER piyush IDENTIFIED BY saraswati DEFAULT TABLESPACE user_data QUOTA UNLIMITED ON user_data QUOTA 20M ON tools; ALTER USER manoj QUOTA 2500K ON tools;
給用戶分配一個簡表
簡表能夠限制用戶在會話時消耗的資源。這些資源包括:鏈接數據庫的時間,空閒時間,
每次會話的邏輯讀數據的數量等等,缺省的簡表對資源無限制。
CREATE USER piyush IDENTIFIED BY saraswati PROFILE TABLESPACE user_data; ALTER USER manoj Temporary TABLESPACE dev1_data;
爲用戶響應指定角色
這個屬性只能由 ALTER USER 語句設置,試圖用 CREATE USER 語句設置將回返回 一個例外。
ALTER USER manoj DEFAULT ROLE ALL EXCEPT salary_adm;
爲用戶的 password 設定到期時間以便在用戶下次登陸時更改
當用戶的 password 到期,在下一次登陸時將強迫修改 password,oracle 提示用戶輸 入舊的 password,而後輸入新的 password。這項功能經常使用於新用戶,當新用戶用缺省的 password 登陸時必須修改當即修改 password.
ALTER USER manoj IDENTIFIED BY welcome; ALTER USER manoj PASSWORD EXPIRE;
鎖定帳號,是用戶不能登陸
ALTER USER ql AC COUNT LOCK
對帳號解鎖,以便用戶能登陸數據庫
ALTER USER ql ACCOUNT UNLOCK
權限和角色
權限容許用戶訪問屬於其它用戶的對象或執行程序,ORACLE 系統提供三種權限:
Object 對象級
System 系統級
Role 角色級
這些權限能夠授予給用戶、特殊用戶 public 或角色,若是授予一個權限給特殊用戶
"Public"(用戶 public 是 oracle 預約義的,每一個用戶享有這個用戶享有的權限) ,那麼就意味 做將該權限授予了該數據庫的全部用戶。
對管理權限而言,角色是一個工具,權限可以被授予給一個角色,角色也能被授予給另
一個角色或用戶。用戶能夠經過角色繼承權限,除了管理權限外角色服務沒有其它目的。權
限能夠被授予,也能夠用一樣的方式撤銷。
創建和使用角色
如前所訴,角色存在的目的就是爲了使權限的管理變得輕鬆。創建角色使用 CREATE ROLE 語句,他的語法以下:
CREATE ROLE role_name IDENTIFIED BY password CREATE ROLE role_name IDENTIFIED EXTERNALLY CREATE ROLE role_name IDENTIFIED GLOBALLY
缺省狀況下創建的角色沒有 password 或者其餘的識別。若是使用 IDENTIFIED BY 子 句創建,那麼角色不會自動響應,必須用 SET ROLE 激活。
SET ROLE role_name IDENTIFIED BY password
EXTERNALLY 和 GLOBALLY 類型的角色由操做系統和 ORACLE Service server 驗
證。一般用戶須要權限修改應用程序中使用的表單中的數據,可是隻有在應用程序運行時而
不是在使用 ad hoc 工具時,這種上下文敏感安全能夠經過有 PASSWORD 的角色來實現。 當用戶在應用程序內部連結數據庫時,代碼將執行 SET ROLE 命令,經過安全驗證。因此 用戶不須要知道角色的 password,也不須要本身輸入 SET ROLE 命令。
對象權限
對象權限就是指在表、視圖、序列、過程、函數或包等對象上執行特殊動做的權利。有
九種不一樣類型的權限能夠授予給用戶或角色。以下表:
權限 ALTER DELETE EXECUTEINDEXINSERTREAD REFERENCESELECT UPDATE Directory no no no no no yes no no no
function no no yes no no no no no no
procedure no no yes no no no no no no
package no no yes no no no no no no
DB Object no no yes no no no no no no
Libary no no yes no no no no no no
Operation no no yes no no no no no no
Sequence yes no no no no no no no no
Table yes yes no yes yes no yes yes yes
Type no no yes no no no no no no
View no yes no no yes no no yes yes
對象由不止一個權限,特殊權限 ALL 能夠被授予或撤銷。如 TABLE 的 ALL 權限就包 括:
SELECT,INSERT,UPDATE 和 DELETE,還有 INDEX,ALTER,和 REFERENCE。
如何看這個表咱們以 ALTER 權限爲例進行說明
ALTER 權限
容許執行 ALTER TABLE 和 LOCK TABLE 操做,ALTER TABLE 能夠進行以下操做:
. 更改表名
. 增長或刪除列
. 改變列的數據類型或大小
. 將錶轉變爲分區表
在SEQUENCE 上的 ALTER 權限容許執行 ALTER Sequence 語句,從新給 sequence 分配小值、增量和緩衝區大小。
系統權限
系統權限須要授予者有進行系統級活動的能力,如鏈接數據庫,更改用戶會話、創建表
或創建用戶等等。你能夠在數據字典視圖 SYSTEM_PRIVILEGE_MAP 上得到完整的系統 權限。對象權限和系統權限都經過 GRANT 語句授予用戶或角色。須要注意的是在授予對象 權限時語句應該是WITH GRANT OPTION子句,但在授予系統權象時語句是WITH ADMIN OPTION,因此在你試圖授予系統權限時,使用語句 WITH GRANT OPTION 系統會報告一
個錯誤:ONLY ADMIN OPTION can be specified。在考試中要特別注意這個語法和錯誤信 息。
角色和角色權限
角色權限就是將屬於用戶的權限授予一個角色。任何權限均可以授予給一個角色。授予
系統權限給被授予者必須使用 WITH_ADMIN_OPTION 子句,在會話期間經過 SET ROLE 語句授予或撤銷角色權限。然而,角色權限不能依靠存儲在 SQL 中的權限。若是函數、程
序、包、觸發器或者方法使用另外一個計劃擁有的對象,那麼就必須直接給對象的擁有者受權,
這是由於權限不會在會話之間改變。
授予和撤銷權限
給用戶或者角色授予權限使用 GRANT 語句,GRANT 語句的語法以下:
GRANT ROLE(或 system privilege) TO user(role,Public) WITH ADMIN OPTION(可選)
對象權限被授予 WITH GRANT OPTION,
權限和數據字典
數據字典是 ORACLE 存儲有關數據庫結構信息的地方,數據自己存放在其餘地方,數
據字典由表和視圖組成。在考試中關於數據字典容易考的內容是:查看那一類權限已經被
授予。好比 DBA_TAB_PRIV 包含了用戶授予給另外一用戶的對象權限和在授予時是否帶有 WITH GRANT OTPION 子串的信息。注意 DBA_TAB_PRIV 不只僅包含了對錶的權限的關
系,他還包括函數、包、隊列等等上的權限的關係。下表列出了全部的權限和角色的數據字
典視圖:
表: 權限的數據字典視圖
視圖 做用 ALL_COL_PRIVS 表示列上的受權,用戶和 PUBLIC 是被授予者 ALL_COL_PRIVS_MADE 表示列上的受權,用戶是屬主和被授予者 ALL_COL_RECD 表示列上的受權,用戶和 PUBLIC 是被授予者 ALL_TAB_PRIVS 表示對象上的受權,用戶是 PUBLIC 或被授予者或用戶是屬主 ALL_TAB_PRIVS_MADE 表示對象上的權限,用戶是屬主或授予者 ALL_TAB_PRIVS_RECD 表示對象上的權限, 用戶是 PUBLIC 或被授予者
DBA_COL_PRIVS 數據庫列上的全部受權 DBA_ROLE_PRIVS 顯示已授予用戶或其餘角色的角色 DBA_SYS_PRIVS 已授予用戶或角色的系統權限 DBA_TAB_PRIVS 數據庫對象上的全部權限 ROLE_ROLE_PRIVS 顯示已授予用戶的角色 ROLE_SYS_PRIVS 顯示經過角色授予用戶的系統權限 ROLE_TAB_PRIVS 顯示經過角色授予用戶的對象權限 SESSION_PRIVS 顯示用戶如今可利用的全部系統權限 USER_COL_PRIVS 顯示列上的權限,用戶是屬主、授予者或被授予者 USER_COL_PRIVS_MADE 顯示列上已授予的權限,用戶是屬主或授予者 USER_COL_PRIVS_RECD 顯示列上已授予的權限,用戶是屬主或被授予者 USER_ROLE_PRIVS 顯示已授予給用戶的全部角色 USER_SYS_PRIVS 顯示已授予給用戶的全部系統權限 USER_TAB_PRIVS 顯示已授予給用戶的全部對象權限 USER_TAB_PRIVS_MADE 顯示已授予給其餘用戶的對象權限,用戶是屬主 USER_TAB_PRIVS_RECD 顯示已授予給其餘用戶的對象權限,用戶是被授予者
遊標
遊標使用大全(1)
SQL 是用於訪問 ORACLE 數據庫的語言,PL/SQL 擴展和增強了 SQL 的功能,它同時
引入了更強的程序邏輯。 PL/SQL 支持 DML 命令和 SQL 的事務控制語句。DDL 在 PL/SQL
中不被支持,這就意味做在 PL/SQL 程序塊中不能建立表或其餘任何對象。較好的 PL/SQL
程序設計是在 PL/SQL 塊中使用象 DBMS_SQL 這樣的內建包或執行 EXECUTE
IMMEDIATE 命令創建動態 SQL 來執行 DDL 命令,PL/SQL 編譯器保證對象引用以及用戶
的權限。
下面咱們將討論各類用於訪問 ORACLE 數據庫的 DDL 和 TCL 語句。
查詢
SELECT 語句用於從數據庫中查詢數據,當在 PL/SQL 中使用 SELECT 語句時,要與
INTO 子句一塊兒使用,查詢的返回值被賦予 INTO 子句中的變量,變量的聲明是在 DELCARE
中。SELECT INTO 語法以下:
SELECT [DISTICT|ALL]{*|column[,column,...]} INTO (variable[,variable,...] |record) FROM {table|(sub-query)}[alias] WHERE............
PL/SQL 中 SELECT 語句只返回一行數據。若是超過一行數據,那麼就要使用顯式遊
標(對遊標的討論咱們將在後面進行),INTO 子句中要有與 SELECT 子句中相同列數量的
變量。INTO 子句中也能夠是記錄變量。
%TYPE 屬性
在PL/SQL 中能夠將變量和常量聲明爲內建或用戶定義的數據類型,以引用一個列名,
同時繼承他的數據類型和大小。這種動態賦值方法是很是有用的,好比變量引用的列的數據
類型和大小改變了,若是使用了%TYPE,那麼用戶就沒必要修改代碼,不然就必須修改代碼。
例:
v_empno SCOTT.EMP.EMPNO%TYPE; v_salary EMP.SALARY%TYPE;
不但列名可使用%TYPE,並且變量、遊標、記錄,或聲明的常量均可以使用%TYPE。
這對於定義相同數據類型的變量很是有用。
DELCARE V_A NUMBER(5):=10; V_B V_A%TYPE:=15; V_C V_A%TYPE; BEGIN DBMS_OUTPUT.PUT_LINE ('V_A='||V_A||'V_B='||V_B||'V_C='||V_C); END
SQL>/ V_A=10 V_B=15 V_C= PL/SQL procedure successfully completed.
SQL>
其餘 DML 語句
其它操做數據的 DML 語句是:INSERT、UPDATE、DELETE 和 LOCK TABLE,這些語
句在 PL/SQL 中的語法與在 SQL 中的語法相同。咱們在前面已經討論過 DML 語句的使用
這裏就再也不重複了。在 DML 語句中可使用任何在 DECLARE 部分聲明的變量,若是是嵌
套塊,那麼要注意變量的做用範圍。
例:
CREATE OR REPLACE PROCEDURE FIRE_EMPLOYEE (pempno in number) AS v_ename EMP.ENAME%TYPE; BEGIN SELECT ename INTO v_ename FROM emp WHERE empno=p_empno;
INSERT INTO FORMER_EMP(EMPNO,ENAME) VALUES (p_empno,v_ename);
DELETE FROM emp WHERE empno=p_empno;
UPDATE former_emp SET date_deleted=SYSDATE WHERE empno=p_empno;
EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('Employee Number Not Found!');
END
DML 語句的結果
當執行一條 DML 語句後,DML 語句的結果保存在四個遊標屬性中,這些屬性用於控制
程序流程或者瞭解程序的狀態。當運行 DML 語句時,PL/SQL 打開一個內建遊標並處理結
果,遊標是維護查詢結果的內存中的一個區域,遊標在運行 DML 語句時打開,完成後關閉。
隱式遊標只使用 SQL%FOUND,SQL%NOTFOUND,SQL%ROWCOUNT 三個屬
性.SQL%FOUND,SQL%NOTFOUND 是布爾值,SQL%ROWCOUNT 是整數值。
SQL%FOUND 和 SQL%NOTFOUND
在執行任何 DML 語句前 SQL%FOUND 和 SQL%NOTFOUND 的值都是 NULL,在執行
DML 語句後,SQL%FOUND 的屬性值將是:
. TRUE :INSERT
. TRUE :DELETE 和 UPDATE,至少有一行被 DELETE 或 UPDATE.
. TRUE :SELECT INTO 至少返回一行
當SQL%FOUND 爲 TRUE 時,SQL%NOTFOUND 爲 FALSE。
SQL%ROWCOUNT
在執行任何 DML 語句以前,SQL%ROWCOUNT 的值都是 NULL,對於 SELECT INTO
語句,若是執行成功,SQL%ROWCOUNT 的值爲 1,若是沒有成功,SQL%ROWCOUNT
的值爲 0,同時產生一個異常 NO_DATA_FOUND.
SQL%ISOPEN
SQL%ISOPEN是一個布爾值,若是遊標打開,則爲TRUE, 若是遊標關閉,則爲FALSE.
對於隱式遊標而言 SQL%ISOPEN 老是 FALSE,這是由於隱式遊標在 DML 語句執行時打
開,結束時就當即關閉。
事務控制語句
事務是一個工做的邏輯單元能夠包括一個或多個 DML 語句,事物控制幫助用戶保證數
據的一致性。若是事務控制邏輯單元中的任何一個 DML 語句失敗,那麼整個事務都將回滾,
在 PL/SQL 中用戶能夠明確地使用 COMMIT、ROLLBACK、SAVEPOINT 以及 SET
TRANSACTION 語句。
COMMIT 語句終止事務,永久保存數據庫的變化,同時釋放全部 LOCK,ROLLBACK
終止現行事務釋放全部 LOCK,但不保存數據庫的任何變化,SAVEPOINT 用於設置中間點,
當事務調用過多的數據庫操做時,中間點是很是有用的,SET TRANSACTION 用於設置事
務屬性,好比 read-write 和隔離級等。
顯式遊標
當查詢返回結果超過一行時,就須要一個顯式遊標,此時用戶不能使用 select into 語句。
PL/SQL 管理隱式遊標,當查詢開始時隱式遊標打開,查詢結束時隱式遊標自動關閉。顯式
遊標在 PL/SQL 塊的聲明部分聲明,在執行部分或異常處理部分打開,取數據,關閉。下表
顯示了顯式遊標和隱式遊標的差異:
表1 隱式遊標和顯式遊標
隱式遊標 顯式遊標
PL/SQL 維護,當執行查詢時自動打開和關閉 在程序中顯式定義、打開、關閉,遊標有一個名字。
遊標屬性前綴是 SQL 遊標屬性的前綴是遊標名
屬性%ISOPEN 老是爲 FALSE %ISOPEN 根據遊標的狀態肯定值
SELECT 語句帶有 INTO 子串,只有一行數據被處理 能夠處理多行數據,在程序中設置循環,取出每一行數據。
遊標
遊標使用大全(2)
使用遊標
這裏要作一個聲明,咱們所說的遊標一般是指顯式遊標,所以從如今起沒有特別指明的
狀況,咱們所說的遊標都是指顯式遊標。要在程序中使用遊標,必須首先聲明遊標。
聲明遊標
語法:
CURSOR cursor_name IS select_statement;
在PL/SQL 中游標名是一個未聲明變量,不能給遊標名賦值或用於表達式中。
例:
DELCARE CURSOR C_EMP IS SELECT empno,ename,salary FROM emp WHERE salary>2000 ORDER BY ename; ........ BEGIN
在遊標定義中 SELECT 語句中不必定非要表能夠是視圖,也能夠從多個表或視圖中選
擇的列,甚至可使用*來選擇全部的列 。
打開遊標
使用遊標中的值以前應該首先打開遊標,打開遊標初始化查詢處理。打開遊標的語法是:
OPEN cursor_name
cursor_name 是在聲明部分定義的遊標名。
例:
OPEN C_EMP;
關閉遊標
語法:
CLOSE cursor_name
例:
CLOSE C_EMP;
從遊標提取數據
從遊標獲得一行數據使用 FETCH 命令。每一次提取數據後,遊標都指向結果集的下一
行。語法以下:
FETCH cursor_name INTO variable[,variable,...]
對於SELECT 定義的遊標的每一列,FETCH 變量列表都應該有一個變量與之相對應,
變量的類型也要相同。
例:
SET SERVERIUTPUT ON DECLARE v_ename EMP.ENAME%TYPE; v_salary EMP.SALARY%TYPE; CURSOR c_emp IS SELECT ename,salary FROM emp; BEGIN OPEN c_emp;
FETCH c_emp INTO v_ename,v_salary; DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary); FETCH c_emp INTO v_ename,v_salary; DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary); FETCH c_emp INTO v_ename,v_salary; DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary); CLOSE c_emp; END
這段代碼無疑是很是麻煩的,若是有多行返回結果,可使用循環並用遊標屬性爲結束
循環的條件,以這種方式提取數據,程序的可讀性和簡潔性都大爲提升,下面咱們使用循環
從新寫上面的程序:
SET SERVERIUTPUT ON DECLARE v_ename EMP.ENAME%TYPE; v_salary EMP.SALARY%TYPE; CURSOR c_emp IS SELECT ename,salary FROM emp; BEGIN OPEN c_emp; LOOP FETCH c_emp INTO v_ename,v_salary; EXIT WHEN c_emp%NOTFOUND; DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary); END
記錄變量
定義一個記錄變量使用 TYPE 命令和%ROWTYPE,關於%ROWsTYPE 的更多信息請
參閱相關資料。
記錄變量用於從遊標中提取數據行,當遊標選擇不少列的時候,那麼使用記錄比爲每列
聲明一個變量要方便得多。
當在表上使用%ROWTYPE 並將從遊標中取出的值放入記錄中時,若是要選擇表中所
有列,那麼在 SELECT 子句中使用*比將全部列名列出來要安全得多。
例:
SET SERVERIUTPUT ON DECLARE R_emp EMP%ROWTYPE; CURSOR c_emp IS SELECT * FROM emp; BEGIN OPEN c_emp; LOOP FETCH c_emp INTO r_emp; EXIT WHEN c_emp%NOTFOUND; DBMS_OUT.PUT.PUT_LINE('Salary of Employee'||r_emp.ename||'is'|| r_emp.salary); END LOOP; CLOSE c_emp; END;
%ROWTYPE 也能夠用遊標名來定義,這樣的話就必需要首先聲明遊標:
SET SERVERIUTPUT ON DECLARE CURSOR c_emp IS SELECT ename,salary FROM emp; R_emp c_emp%ROWTYPE; BEGIN OPEN c_emp; LOOP FETCH c_emp INTO r_emp; EXIT WHEN c_emp%NOTFOUND; DBMS_OUT.PUT.PUT_LINE('Salary of Employee'||r_emp.ename||'is'|| r_emp.salary); END LOOP; CLOSE c_emp; END;
帶參數的遊標
與存儲過程和函數類似,能夠將參數傳遞給遊標並在查詢中使用。這對於處理在某種條
件下打開遊標的狀況很是有用。它的語法以下:
CURSOR cursor_name[(parameter[,parameter],...)] IS select_statement;
定義參數的語法以下:
Parameter_name [IN] data_type[{:=|DEFAULT} value]
與存儲過程不一樣的是,遊標只能接受傳遞的值,而不能返回值。參數只定義數據類型,
沒有大小。
另外能夠給參數設定一個缺省值,當沒有參數值傳遞給遊標時,就使用缺省值。遊標中
定義的參數只是一個佔位符,在別處引用該參數不必定可靠。
在打開遊標時給參數賦值,語法以下:
OPEN cursor_name[value[,value]....];
參數值能夠是文字或變量。
例:
DECALRE
CURSOR c_dept IS SELECT * FROM dept ORDER BY deptno;
CURSOR c_emp (p_dept VARACHAR2) IS SELECT ename,salary FROM emp WHERE deptno=p_dept ORDER BY ename r_dept DEPT%ROWTYPE; v_ename EMP.ENAME%TYPE; v_salary EMP.SALARY%TYPE; v_tot_salary EMP.SALARY%TYPE;
BEGIN
OPEN c_dept; LOOP FETCH c_dept INTO r_dept; EXIT WHEN c_dept%NOTFOUND; DBMS_OUTPUT.PUT_LINE('Department:'|| r_dept.deptno||'-'||r_dept.dname); v_tot_salary:=0; OPEN c_emp(r_dept.deptno); LOOP FETCH c_emp INTO v_ename,v_salary; EXIT WHEN c_emp%NOTFOUND; DBMS_OUTPUT.PUT_LINE('Name:'|| v_ename||' salary:'||v_salary); v_tot_salary:=v_tot_salary+v_salary; END LOOP; CLOSE c_emp; DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:'|| v_tot_salary); END LOOP; CLOSE c_dept; END;
遊標
遊標使用大全(3)
遊標FOR 循環
在大多數時候咱們在設計程序的時候都遵循下面的步驟:
一、打開遊標
二、開始循環
三、從遊標中取值
四、檢查那一行被返回
五、處理
六、關閉循環
七、關閉遊標
能夠簡單的把這一類代碼稱爲遊標用於循環。但還有一種循環與這種類型不相同,這就
是 FOR 循環,用於 FOR 循環的遊標按照正常的聲明方式聲明,它的優勢在於不須要顯式 的打開、關閉、取數據,測試數據的存在、定義存放數據的變量等等。遊標 FOR 循環的語
法以下:
FOR record_name IN (corsor_name[(parameter[,parameter]...)] | (query_difinition) LOOP statements END LOOP;
下面咱們用 for 循環重寫上面的例子:
DECALRE
CURSOR c_dept IS SELECT deptno,dname FROM dept ORDER BY deptno; CURSOR c_emp (p_dept VARACHAR2) IS SELECT ename,salary FROM emp WHERE deptno=p_dept ORDER BY ename
v_tot_salary EMP.SALARY%TYPE;
BEGIN
FOR r_dept IN c_dept LOOP DBMS_OUTPUT.PUT_LINE('Department:'|| r_dept.deptno||'-'||r_dept.dname); v_tot_salary:=0; FOR r_emp IN c_emp(r_dept.deptno) LOOP DBMS_OUTPUT.PUT_LINE('Name:'|| v_ename||' salary:'||v_salary); v_tot_salary:=v_tot_salary+v_salary; END LOOP; DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:'|| v_tot_salary); END LOOP;
END;
在遊標 FOR 循環中使用查詢
在遊標 FOR 循環中能夠定義查詢,因爲沒有顯式聲明因此遊標沒有名字,記錄名經過 遊標查詢來定義。
DECALRE
v_tot_salary EMP.SALARY%TYPE;
BEGIN
FOR r_dept IN (SELECT deptno,dname FROM dept ORDER BY deptno) LOOP DBMS_OUTPUT.PUT_LINE('Department:'|| r_dept.deptno||'-'||r_dept.dname); v_tot_salary:=0; FOR r_emp IN (SELECT ename,salary FROM emp WHERE deptno=p_dept ORDER BY ename) LOOP DBMS_OUTPUT.PUT_LINE('Name:'|| v_ename||' salary:'||v_salary); v_tot_salary:=v_tot_salary+v_salary; END LOOP; DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:'|| v_tot_salary); END LOOP;
END;
遊標中的子查詢
語法以下:
CURSOR C1 IS SELECT * FROM emp WHERE deptno NOT IN (SELECT deptno FROM dept WHERE dname!='ACCOUNTING');
能夠看出與 SQL 中的子查詢沒有什麼區別。
遊標中的更新和刪除
在PL/SQL 中依然可使用 UPDATE 和 DELETE 語句更新或刪除數據行。顯式遊標只 有在須要得到多行數據的狀況下使用。PL/SQL 提供了僅僅使用遊標就能夠執行刪除或更新 記錄的方法。
UPDATE或DELETE語句中的WHERE CURRENT OF子串專門處理要執行UPDATE 或 DELETE 操做的表中取出的近的數據。要使用這個方法,在聲明遊標時必須使用 FOR UPDATE 子串,當對話使用 FOR UPDATE 子串打開一個遊標時,全部返回集中的數據行 都將處於行級(ROW-LEVEL)獨佔式鎖定,其餘對象只能查詢這些數據行,不能進行 UPDATE、DELETE 或 SELECT...FOR UPDATE 操做。
語法:
FOR UPDATE [OF [schema.]table.column[,[schema.]table.column].. [nowait]
在多表查詢中,使用 OF 子句來鎖定特定的表,若是忽略了 OF 子句,那麼全部表中選 擇的數據行都將被鎖定。若是這些數據行已經被其餘會話鎖定,那麼正常狀況下 ORACLE 將等待,直到數據行解鎖。
在UPDATE 和 DELETE 中使用 WHERE CURRENT OF 子串的語法以下:
WHERE{CURRENT OF cursor_name|search_condition}
例:
DELCARE
CURSOR c1 IS SELECT empno,salary FROM emp WHERE comm IS NULL FOR UPDATE OF comm;
v_comm NUMBER(10,2);
BEGIN
FOR r1 IN c1 LOOP
IF r1.salary<500 THEN v_comm:=r1.salary*0.25; ELSEIF r1.salary<1000 THEN v_comm:=r1.salary*0.20; ELSEIF r1.salary<3000 THEN v_comm:=r1.salary*0.15; ELSE v_comm:=r1.salary*0.12; END IF;
UPDATE emp; SET comm=v_comm WHERE CURRENT OF c1l;
END LOOP; END
異常處理
異常處理初步(1)
PL/SQL 處理異常不一樣於其餘程序語言的錯誤管理方法,PL/SQL 的異常處理機制與 ADA
很類似,有一個處理錯誤的全包含方法。當發生錯誤時,程序無條件轉到異常處理部分,這
就要求代碼要很是乾淨並把錯誤處理部分和程序的其它部分分開。oracle 容許聲明其餘異常
條件類型以擴展錯誤/異常處理。這種擴展使 PL/SQL 的異常處理很是靈活。
當一個運行時錯誤發生時,稱爲一個異常被拋出。PL/SQL 程序編譯時的錯誤不是能被
處理得異常,只有在運行時的異常能被處理。在 PL/SQL 程序設計中異常的拋出和處理是非
常重要的內容。
拋出異常
由三種方式拋出異常
. 經過 PL/SQL 運行時引擎
. 使用 RAISE 語句
. 調用 RAISE_APPLICATION_ERROR 存儲過程
當數據庫或 PL/SQL 在運行時發生錯誤時,一個異常被 PL/SQL 運行時引擎自動拋出。
異常也能夠經過 RAISE 語句拋出
RAISE exception_name;
顯式拋出異常是程序員處理聲明的異常的習慣用法,但 RAISE 不限於聲明瞭的異常,
它能夠拋出任何任何異常。例如,你但願用 TIMEOUT_ON_RESOURCE 錯誤檢測新的運
行時異常處理器,你只需簡單的在程序中使用下面的語句:
RAISE TIMEOUT_ON_RESOUCE;
下面看一個訂單輸入系統,當庫存小於訂單時拋出一個 inventory_too_low 異常。
DECLARE inventory_too_low EXCEPTION; ---其餘聲明語句 BEGIN . . IF order_rec.qty>inventory_rec.qty THEN RAISE inventory_too_low; END IF . . EXCEPTION WHEN inventory_too_low THEN order_rec.staus:='backordered'; replenish_inventory(inventory_nbr=> inventory_rec.sku,min_amount=>order_rec.qty-inventory_rec.qty); END;
這裏replenish_inventory 是一個觸發器。
處理異常
PL/SQL 程序塊的異常部分包含了程序處理錯誤的代碼,當異常被拋出時,一個異常陷
阱就自動發生,程序控制離開執行部分轉入異常部分,一旦程序進入異常部分就不能再回到
同一塊的執行部分。下面是異常部分的通常語法:
EXCEPTION WHEN exception_name THEN Code for handing exception_name [WHEN another_exception THEN Code for handing another_exception] [WHEN others THEN code for handing any other exception.]
用戶必須在獨立的 WHEN 子串中爲每一個異常設計異常處理代碼,WHEN OTHERS 子
串必須放置在後面做爲缺省處理器處理沒有顯式處理的異常。當異常發生時,控制轉到異
常部分,ORACLE 查找當前異常相應的 WHEN..THEN 語句,捕捉異常,THEN 以後的代
碼被執行,若是錯誤陷阱代碼只是退出相應的嵌套塊,那麼程序將繼續執行內部塊 END 後
面的語句。若是沒有找到相應的異常陷阱,那麼將執行 WHEN OTHERS。在異常部分 WHEN
子串沒有數量限制。
EXCEPTION
WHEN inventory_too_low THEN order_rec.staus:='backordered'; replenish_inventory(inventory_nbr=> inventory_rec.sku,min_amount=>order_rec.qty-inventory_rec.qty); WHEN discontinued_item THEN --code for discontinued_item processing WHEN zero_divide THEN --code for zero_divide WHEN OTHERS THEN --code for any other exception END;
當異常拋出後,控制無條件轉到異常部分,這就意味着控制不能回到異常發生的位置,
當異常被處理和解決後,控制返回到上一層執行部分的下一條語句。
BEGIN DECLARE bad_credit; BEGIN
RAISE bad_credit; --發生異常,控制轉向; EXCEPTION WHEN bad_credit THEN dbms_output.put_line('bad_credit'); END;
--bad_credit 異常處理後,控制轉到這裏 EXCEPTION WHEN OTHERS THEN --控制不會從 bad_credit 異常轉到這裏 --由於 bad_credit 已被處理 END;
當異常發生時,在塊的內部沒有該異常處理器時,控制將轉到或傳播到上一層塊的異常
處理部分。
BEGIN DECLARE ---內部塊開始 bad_credit; BEGIN RAISE bad_credit; --發生異常,控制轉向; EXCEPTION WHEN ZERO_DIVIDE THEN --不能處理 bad_credite 異常 dbms_output.put_line('divide by zero error'); END --結束內部塊
--控制不能到達這裏,由於異常沒有解決; --異常部分
EXCEPTION WHEN OTHERS THEN --因爲 bad_credit 沒有解決,控制將轉到這裏 END;
異常傳播
沒有處理的異常將沿檢測異常調用程序傳播到外面,當異常被處理並解決或到達程序
外層 ネV埂?BR>在聲明部分拋出的異常將控制轉到上一層的異常部分。
BEGIN executable statements BEGIN today DATE:='SYADATE'; --ERRROR BEGIN --內部塊開始 dbms_output.put_line('this line will not execute'); EXCEPTION WHEN OTHERS THEN --異常不會在這裏處理 END;--內部塊結束
EXCEPTION WHEN OTHERS THEN 處理異常 END
執行部分拋出的異常將首先傳遞到同一塊的異常部分,若是在同一塊的異常部分沒有處
理這個異常的處理器,那麼異常將會傳播到上一層的異常部分中,一直到外層。
在異常部分拋出的異常將控制轉到上一層的異常部分。
處理異常將中止異常的傳播和解決。有時用戶但願在錯誤發生時,程序仍然能執行一些
動做,要達到這個目的,能夠把但願執行的動做放在異常處理器中,而後執行不帶參數的
RAISE 語句,RAISE 語句將從新拋出出現的異常,容許他繼續傳播。
DECLARE order_too_old EXCEPTION; BEGIN RAISE order_too_old; EXCEPTION WHEN order_too_old THEN DECLARE
file_handle UTL_FILE.FILE_TYPE; BEGIN --open file file_handle:=UTL_FILE.FOPEN (location=>'/ora01/app/oracle/admin/test/utlsir' ,filename=>'error.log' .open_mode=>'W'); --write error stack UTL_FILE.PUT_LINE(filehandle, DBMS_UTILITY.FORMAT_ERROR_STACK); --write the call stack UTL_FILE.PUT_LINE(filehandle, DBMS_UTILITY.FORMAT_CALL_STACK); --close error log UTL_FILE.FCLOSE(file_handle); RAISE; --re-raise the exception END END
若是從 FORMAT_XXX_STACK 輸出一個很大的值,那麼使用 DBMS_OUTPUT 或
UTL_FILE 顯示錯誤或調用堆的異常部分自身也會拋出異常,這兩個堆常規下多能返回
2000 字節,但 utl_file.put_line 被限制在 1000 字節之內,而 dbms_output.put_line 限制在
512 字節內。若是使用前面的代碼而且不容許這種可能性,那麼在異常處理器中將拋出一個
未處理的異常。
GOTO 語句不能用於將控制從執行部分傳遞到異常部分或反之。
已命名異常
在PL/SQL 塊的異常部分只有已命名的異常才能被 WHEN 子串處理,ORACLE 包含了
一系列已命名的異常,這些異常都聲明在 STANDARD 包中,這些內建異常在這裏就不一一
講述,有興趣的讀者能夠查閱有關資料。
異常處理
異常處理初步(2)
PL/SQL 處理異常不一樣於其餘程序語言的錯誤管理方法,PL/SQL 的異常處理機制與 ADA
很類似,有一個處理錯誤的全包含方法。當發生錯誤時,程序無條件轉到異常處理部分,這
就要求代碼要很是乾淨並把錯誤處理部分和程序的其它部分分開。oracle 容許聲明其餘異常
條件類型以擴展錯誤/異常處理。這種擴展使 PL/SQL 的異常處理很是靈活。
當一個運行時錯誤發生時,稱爲一個異常被拋出。PL/SQL 程序編譯時的錯誤不是能被
處理得異常,只有在運行時的異常能被處理。在 PL/SQL 程序設計中異常的拋出和處理是非
常重要的內容。
拋出異常
由三種方式拋出異常
. 經過 PL/SQL 運行時引擎
. 使用 RAISE 語句
. 調用 RAISE_APPLICATION_ERROR 存儲過程
當數據庫或 PL/SQL 在運行時發生錯誤時,一個異常被 PL/SQL 運行時引擎自動拋出。
異常也能夠經過 RAISE 語句拋出
RAISE exception_name;
顯式拋出異常是程序員處理聲明的異常的習慣用法,但 RAISE 不限於聲明瞭的異常,
它能夠拋出任何任何異常。例如,你但願用 TIMEOUT_ON_RESOURCE 錯誤檢測新的運
行時異常處理器,你只需簡單的在程序中使用下面的語句:
RAISE TIMEOUT_ON_RESOUCE;
下面看一個訂單輸入系統,當庫存小於訂單時拋出一個 inventory_too_low 異常。
DECLARE inventory_too_low EXCEPTION; ---其餘聲明語句 BEGIN . . IF order_rec.qty>inventory_rec.qty THEN RAISE inventory_too_low; END IF . . EXCEPTION WHEN inventory_too_low THEN order_rec.staus:='backordered'; replenish_inventory(inventory_nbr=> inventory_rec.sku,min_amount=>order_rec.qty-inventory_rec.qty); END;
這裏replenish_inventory 是一個觸發器。
處理異常
PL/SQL 程序塊的異常部分包含了程序處理錯誤的代碼,當異常被拋出時,一個異常陷
阱就自動發生,程序控制離開執行部分轉入異常部分,一旦程序進入異常部分就不能再回到
同一塊的執行部分。下面是異常部分的通常語法:
EXCEPTION WHEN exception_name THEN Code for handing exception_name [WHEN another_exception THEN Code for handing another_exception] [WHEN others THEN code for handing any other exception.]
用戶必須在獨立的 WHEN 子串中爲每一個異常設計異常處理代碼,WHEN OTHERS 子
串必須放置在後面做爲缺省處理器處理沒有顯式處理的異常。當異常發生時,控制轉到異
常部分,ORACLE 查找當前異常相應的 WHEN..THEN 語句,捕捉異常,THEN 以後的代
碼被執行,若是錯誤陷阱代碼只是退出相應的嵌套塊,那麼程序將繼續執行內部塊 END 後
面的語句。若是沒有找到相應的異常陷阱,那麼將執行 WHEN OTHERS。在異常部分 WHEN
子串沒有數量限制。
EXCEPTION
WHEN inventory_too_low THEN order_rec.staus:='backordered'; replenish_inventory(inventory_nbr=> inventory_rec.sku,min_amount=>order_rec.qty-inventory_rec.qty); WHEN discontinued_item THEN --code for discontinued_item processing WHEN zero_divide THEN --code for zero_divide WHEN OTHERS THEN --code for any other exception END;
當異常拋出後,控制無條件轉到異常部分,這就意味着控制不能回到異常發生的位置,
當異常被處理和解決後,控制返回到上一層執行部分的下一條語句。
BEGIN DECLARE bad_credit; BEGIN RAISE bad_credit; --發生異常,控制轉向; EXCEPTION WHEN bad_credit THEN dbms_output.put_line('bad_credit'); END;
--bad_credit 異常處理後,控制轉到這裏 EXCEPTION WHEN OTHERS THEN --控制不會從 bad_credit 異常轉到這裏 --由於 bad_credit 已被處理 END;
當異常發生時,在塊的內部沒有該異常處理器時,控制將轉到或傳播到上一層塊的異常
處理部分。
BEGIN DECLARE ---內部塊開始 bad_credit; BEGIN RAISE bad_credit; --發生異常,控制轉向; EXCEPTION WHEN ZERO_DIVIDE THEN --不能處理 bad_credite 異常 dbms_output.put_line('divide by zero error'); END --結束內部塊
--控制不能到達這裏,由於異常沒有解決; --異常部分
EXCEPTION WHEN OTHERS THEN --因爲 bad_credit 沒有解決,控制將轉到這裏 END;
異常傳播
沒有處理的異常將沿檢測異常調用程序傳播到外面,當異常被處理並解決或到達程序
外層傳播中止。
在聲明部分拋出的異常將控制轉到上一層的異常部分。
BEGIN executable statements BEGIN today DATE:='SYADATE'; --ERRROR BEGIN --內部塊開始 dbms_output.put_line('this line will not execute'); EXCEPTION WHEN OTHERS THEN --異常不會在這裏處理 END;--內部塊結束
EXCEPTION WHEN OTHERS THEN 處理異常 END
執行部分拋出的異常將首先傳遞到同一塊的異常部分,若是在同一塊的異常部分沒有處
理這個異常的處理器,那麼異常將會傳播到上一層的異常部分中,一直到外層。
在異常部分拋出的異常將控制轉到上一層的異常部分。
處理異常將中止異常的傳播和解決。有時用戶但願在錯誤發生時,程序仍然能執行一些
動做,要達到這個目的,能夠把但願執行的動做放在異常處理器中,而後執行不帶參數的
RAISE 語句,RAISE 語句將從新拋出出現的異常,容許他繼續傳播。
DECLARE order_too_old EXCEPTION; BEGIN RAISE order_too_old; EXCEPTION WHEN order_too_old THEN DECLARE file_handle UTL_FILE.FILE_TYPE; BEGIN --open file file_handle:=UTL_FILE.FOPEN (location=>'/ora01/app/oracle/admin/test/utlsir' ,filename=>'error.log' .open_mode=>'W'); --write error stack UTL_FILE.PUT_LINE(filehandle, DBMS_UTILITY.FORMAT_ERROR_STACK); --write the call stack UTL_FILE.PUT_LINE(filehandle, DBMS_UTILITY.FORMAT_CALL_STACK); --close error log UTL_FILE.FCLOSE(file_handle); RAISE; --re-raise the exception END END
若是從 FORMAT_XXX_STACK 輸出一個很大的值,那麼使用 DBMS_OUTPUT 或
UTL_FILE 顯示錯誤或調用堆的異常部分自身也會拋出異常,這兩個堆常規下多能返回
2000 字節,但 utl_file.put_line 被限制在 1000 字節之內,而 dbms_output.put_line 限制在
512 字節內。若是使用前面的代碼而且不容許這種可能性,那麼在異常處理器中將拋出一個
未處理的異常。
GOTO 語句不能用於將控制從執行部分傳遞到異常部分或反之。
已命名異常 在PL/SQL 塊的異常部分只有已命名的異常才能被 WHEN 子串處理,ORACLE 包含了一系列已命名的異常,這些異常都聲明在 STANDARD 包中,這些內建異常在這裏就不一一講述