Oracle資料庫之FORALL與BULK COLLECT語句
我們再來看一下PL/SQL塊的執行過程:當PL/SQL運作時引擎處理一塊代碼時,它使用PL/SQL引擎來執行過程化的代碼,而将SQL語句發送給SQL引擎來執行;SQL引擎執行完畢後,将結果再傳回給PL/SQL引擎。這種在PL/SQL引擎和SQL引擎之間的互動,稱為上下文交換(context switch)。每發生一次交換,就會帶來一定的額外開銷。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICN5QjNykTNyIjNxYDM1EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
FORALL,用于增強PL/SQL引擎到SQL引擎的交換。
BULK COLLECT,用于增強SQL引擎到PL/SQL引擎的交換。(前面我們已經介紹過了)
1. FORALL介紹
使用FORALL,可以将多個DML批量發送給SQL引擎來執行,最大限度地減少上下文互動所帶來的開銷。下面是 FORALL 的一個示意圖:
文法:
說明:
index_name:一個無需聲明的辨別符,作為集合下标使用。
lower_bound .. upper_bound:數字表達式,來指定一組連續有效的索引數字下限和上限。該表達式隻需解析一次。
INDICES OF collection_name:用于指向稀疏數組的實際下标。跳過沒有指派的元素,例如被 DELETE 的元素,NULL 也算值。
VALUES OF index_collection_name:把該集合中的值當作下标,且該集合值的類型隻能是 PLS_INTEGER/BINARY_INTEGER。
SAVE EXCEPTIONS:可選關鍵字,表示即使一些DML語句失敗,直到FORALL LOOP執行完畢才抛出異常。可以使用SQL%BULK_EXCEPTIONS 檢視異常資訊。
dml_statement:靜态語句,例如:UPDATE或者DELETE;或者動态(EXECUTE IMMEDIATE)DML語句。
2. FORALL的使用
示例所使用表結構:
示例1,使用FORALL批量插入、修改、删除資料:
示例2,使用INDICES OF子句:
示例3,使用VALUES OF子句:
3. FORALL注意事項
使用FORALL時,應該遵循如下規則:
FORALL語句的執行體,必須是一個單獨的DML語句,比如INSERT,UPDATE或DELETE。
不要顯式定義index_row,它被PL/SQL引擎隐式定義為PLS_INTEGER類型,并且它的作用域也僅僅是FORALL。
這個DML語句必須與一個集合的元素相關,并且使用FORALL中的index_row來索引。注意不要因為index_row導緻集合下标越界。
lower_bound和upper_bound之間是按照步進 1 來遞增的。
在sql_statement中,不能單獨地引用集合中的元素,隻能批量地使用集合。
在sql_statement中使用的集合,下标不能使用表達式。
4. BULK COLLECT介紹
BULK COLLECT子句會批量檢索結果,即一次性将結果集綁定到一個集合變量中,并從SQL引擎發送到PL/SQL引擎。
通常可以在SELECT INTO、FETCH INTO以及RETURNING INTO子句中使用BULK COLLECT。下面逐一描述BULK COLLECT在這幾種情形下的用法。
5. BULK COLLECT的使用
5.1 在SELECT INTO中使用BULK COLLECT
示例:
說明:使用BULK COLLECT一次即可提取所有行并綁定到記錄變量,這就是所謂的批量綁定。
5.2 在FETCH INTO中使用BULK COLLECT
在遊标中可以使用BLUK COLLECT一次取出一個資料集合,比用遊标單條取資料效率高,尤其是在網絡不大好的情況下。
在使用BULK COLLECT子句時,對于集合類型會自動對其進行初始化以及擴充。是以如果使用BULK COLLECT子句操作集合,則無需對集合進行初始化以及擴充。由于BULK COLLECT的批量特性,如果資料量較大,而集合在此時又自動擴充,為避免過大的資料集造成性能下降,是以可以使用LIMIT子句來限制一次提取的資料量。LIMIT子句隻允許出現在FETCH操作語句的批量中。
5.3 在RETURNING INTO中使用BULK COLLECT
BULK COLLECT除了與SELECT,FETCH進行批量綁定之外,還可以與INSERT,DELETE,UPDATE語句結合使用。當與這幾個DML語句結合時,需要使用RETURNING子句來實作批量綁定。
6. BULK COLLECT的注意事項
BULK COLLECT INTO 的目标對象必須是集合類型。
隻能在伺服器端的程式中使用BULK COLLECT,如果在用戶端使用,就會産生一個不支援這個特性的錯誤。
不能對使用字元串類型作鍵的關聯數組使用BULK COLLECT子句。
複合目标(如對象類型)不能在RETURNING INTO子句中使用。
如果有多個隐式的資料類型轉換的情況存在,多重複合目标就不能在BULK COLLECT INTO子句中使用。
如果有一個隐式的資料類型轉換,複合目标的集合(如對象類型集合)就不能用于BULK COLLECTINTO子句中。
7. FORALL與BULK COLLECT綜合運用
FORALL與BULK COLLECT是實作批量SQL的兩個重要方式,我們可以将其結合使用以提高性能。
1. 什麼是事務
在資料庫中事務是工作的邏輯單元,一個事務是由一個或多個完成一組的相關行為的SQL語句組成,通過事務機制確定這一組SQL語句所作的操作要麼都成功執行,完成整個工作單元操作,要麼一個也不執行。
如:網上轉帳就是典型的要用事務來處理,用以保證資料的一緻性。
2. 事務特性
SQL92标準定義了資料庫事務的四個特點:(面試時可能會問的)
原子性(Atomicity):一個事務裡面所有包含的SQL語句是一個執行整體,不可分割,要麼都做,要麼都不做。
一緻性(Consistency):事務開始時,資料庫中的資料是一緻的,事務結束時,資料庫的資料也應該是一緻的。
隔離性(Isolation):是指資料庫允許多個并發事務同時對其中的資料進行讀寫和修改的能力,隔離性可以防止事務的并發執行時,由于他們的操作指令交叉執行而導緻的資料不一緻狀态。
持久性 (Durability) : 是指當事務結束後,它對資料庫中的影響是永久的,即便系統遇到故障的情況下,資料也不會丢失。
一組SQL語句操作要成為事務,資料庫管理系統必須保證這組操作的原子性(Atomicity)、一緻性(consistency)、隔離性(Isolation)和持久性(Durability),這就是ACID特性。