如下內容整理自網絡sql
1. 一般在SQL語句中給PL/SQL變量賦值叫作綁定(Binding),一次綁定一個完整的集合稱爲批量綁定(Bulk Binding)。數據庫
2. 批量綁定(Bulk binds)能夠經過減小在PL/SQL和SQL引擎之間的上下文切換(context switches )提升了性能. 產生的結果是在單程訪問SQL Server引擎過程當中執行的一組迭代,而不是SQL與PL/SQL之間的交替。這減小了兩個引擎間上下文切換的額外負擔。網絡
缺點是:若是任何數據值產生了無效的更新(UPDATE),整組迭代都將被退回。oracle
3. 批量綁定(Bulk binds)包括:oop
(1) Input collections, use the FORALL statement,通常用來改善DML(INSERT、UPDATE和DELETE) 操做的性能。性能
(2) Output collections, use BULK COLLECT clause,通常用來提升查詢(SELECT)的性能。測試
從9i開始,oracle提供批量綁定關鍵詞forall和bulk collect經過批量綁定技術,極大地加快了數據的處理速度。在不使用批量綁定的時候,爲了將嵌套表中的數據插入數據庫表中,須要循環執行insert語句,而使用forall關鍵詞可讓全部插入內容集中在一次insert中執行,從而加快了執行速度。Bulk collect子句用於取得批量數據,該子句只能用於select語句、fetch語句和DML返回子句中;而forall語句只適用於執行批量的DML操做。fetch
4. 如下經過實例說明:code
1)下面我們對比一下for與forall的效率:get
a. 建立測試表:
[sql] view plaincopy
01.SQL> create table test(id number(10),name varchar2(80));
02.
03.表已建立。
b. 執行測試PL/SQL block:
[sql] view plaincopy
01.declare
02. type id_table_type is table of number(10) index by binary_integer;
03. type name_table_type is table of varchar2(80) index by binary_integer;
04. id_table id_table_type;
05. name_table name_table_type;
06. start_time number(10);
07. end_time number(10);
08.begin
09. for i in 1..100000 loop
10. id_table(i) := i;
11. name_table(i) :='dylan'||i;
12. end loop;
13. delete from test;
14. start_time:=dbms_utility.get_time;
15. for i in 1..100000 loop
16. insert into test values(id_table(i), name_table(i));
17. end loop;
18. end_time := dbms_utility.get_time;
19. dbms_output.put_line('循環cost: '||to_char((end_time-start_time)/100));
20. delete from test;
21. start_time := dbms_utility.get_time;
22. forall i in 1..100000
23. insert into test values(id_table(i), name_table(i));
24. end_time := dbms_utility.get_time;
25. dbms_output.put_line('批量綁定cost: '||to_char((end_time-start_time)/100));
26.end;
27./
c. 測試結果:
循環cost: 3.8
批量綁定cost: .27
PL/SQL 過程已成功完成。
2)在9i中使用forall語句時,必須具備連續的元素;從10g開始,經過使用indices of子句和values of子句,可使用不連續的集合元素,這裏forall跟for不同的是它並非一個循環語句。從10g開始,forall的語句有三種執行語法:
Forall index in lower_bound..upper_bound sql_statement; 其中index是隱含定義的整數變量,lower_bound和upper_bound爲集合元素的上下限。
Forall index in indices of collection [between lower_bound..upper_bound] sql_statement;其中collection爲嵌套表名稱,這裏只取嵌套表collection中下標位於lower_bound和upper_bound之間的非空元素值。
Forall index in values of index_collection sql_statement; 其中index_collection爲存儲下標的集合變量,就是說本集合變量的內容爲要取的集合collection的下標,例如(2,3,5)。
另外,爲了記錄forall更新的行數,特別定義了sql%bulk_rowcount,使用方法以下:
[sql] view plaincopy
01.declare
02. type test_table_type is table of varchar2(100);
03. test_table test_table_type := test_table_type('dylan2','name','asdf');
04.begin
05. forall i in 1..test_table.count
06. update test set name = 'lucy' where name = test_table(i);
07. dbms_output.put_line('第二個元素更新的行數:'||sql%bulk_rowcount(1));
08. dbms_output.put_line('第二個元素更新的行數:'||sql%bulk_rowcount(2));
09. dbms_output.put_line('第二個元素更新的行數:'||sql%bulk_rowcount(3));
10.end;
第二個元素更新的行數:1
第二個元素更新的行數:0
第二個元素更新的行數:0
PL/SQL 過程已成功完成。
3)bulk collect子句的另一個使用環境就是在DML的返回子句中,執行dml操做會改變數據庫數據,爲了取得dml操做改變的數據,可使用returning子句,爲了取得dml所做用的多行數據,則須要使用bulk collect子句。例如:
[sql] view plaincopy
01.declare
02. type test_table_type is table of varchar2(20) index by binary_integer;
03. test_table test_table_type;
04.begin
05. delete from test where name like 'dylan2222%'
06. returning name bulk collect into test_table;
07. for i in 1..test_table.count loop
08. dbms_output.put_line(test_table(i));
09. end loop;
10.end;
dylan2222
dylan22220
dylan22221
dylan22222
dylan22223
dylan22224
dylan22225
dylan22226
dylan22227
dylan22228
dylan22229
PL/SQL 過程已成功完成。
4)使用SAVE EXCEPTION語句處理Forall異常:
[sql] view plaincopy
01.declare
02.type NumList is table of number;
03.num_tab NumList :=NumList(100,0,110,300,0,199,200,0,400);
04.bulk_errors EXCEPTION;
05.PRAGMA EXCEPTION_INIT (bulk_errors, -24381);
06.begin
07. forall i in num_tab.first..num_tab.last
08. SAVE EXCEPTIONS
09. delete from orders where order_total < 500000/num_tab(i);
10.EXCEPTION WHEN bulk_errors THEN
11. dbms_output.put_line('Number of errors is: '|| SQL%BULK_EXCEPTIONS.COUNT);
12. for j in 1..SQL%BULK_EXCEPTIONS.COUNT loop
13. dbms_output.put_line(to_char(SQL%BULK_EXCEPTIONS(j).error_index)
14. || '/' || SQLERRM(-SQL%BULK_EXCEPTIONS(j).error_code));
15. end loop;
16.end;
Number of errors is: 3
2/ORA-01476: 除數爲 0
5/ORA-01476: 除數爲 0
8/ORA-01476: 除數爲 0
PL/SQL 過程已成功完成。
present by dylan.