Oracle Bulk Binding

如下內容整理自網絡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.

相關文章
相關標籤/搜索