Oracle PL/SQL Forall

PL/SQL引擎会执行过程化语句,但它把SQL语句发送给SQL引擎处理,然后SQL引擎把处理的结果返回给PL/SQL引擎。


PL/SQLSQL引擎间的频繁切换会大大降低效率。典型的情况就是在一个循环中反复执行SQL语句。

例如,下面的DELETE语句就会在FOR循环中被多次发送到SQL引擎中去:

Declare
  Type numlist Is Varray(20) Of Number;
  depts numlist := numlist(10,30,70);
--department numbers
Begin
  For i In depts.First .. depts.Last Loop
   Delete From emp Where deptno = depts(i);
  End Loop;
End;


这种情况下,如果SQL语句影响了四行或更多行时,使用批量绑定就会显著地提高性能。


SQL语句中为PL/SQL变量赋值称为绑定,PL/SQL绑定操作可以分为三种:

1.   内绑定(in-bind):用INSERTUPDATE语句将PL/SQL变量或主变量保存到数据库。 

2.   外绑定(out-bind):通过INSERTUPDATEDELETE语句的RETURNING子句的返回值为PL/SQL变量或主变量赋值。 

3.   定义(define):使用SELECTFETCH语句为PL/SQL变量或主变量赋值。 

DML语句可以一次性传递集合中所有的元素,这个过程就是批量绑定。如果集合有20个元素,批量绑定的一次操作就相当于行20SELECTINSERTUPDATEDELETE语句。

这项技术是靠减少PL/SQLSQL引擎间的切换次数来提高性能的。

要对INSERTUPDATEDELETE语句使用批量绑定,就要用PL/SQLFORALL语句。

如果要在SELECT语句中使用批量绑定,我们就要在SELECT语句后面加上一个BULK COLLECT子句来代替INTO子句。


例一:对DELETE语句应用批量绑定 

下面的DELETE语句只往SQL引擎中发送一次,即使是执行了三次DELETE操作:

Declare
 Type numlist Is Varray(20) Of Number;
  depts numlist := numlist(10,30,70);
--department numbers
Begin
 Forall i In depts.First .. depts.Last
   Delete From emp Where deptno = depts(i);
End;

这种情况下,如果SQL语句影响了四行或更多行时,使用批量绑定就会显著地提高性能。

1、批量绑定如何提高性能

SQL语句中为PL/SQL变量赋值称为绑定,PL/SQL绑定操作可以分为三种:

1.   内绑定(in-bind):用INSERTUPDATE语句将PL/SQL变量或主变量保存到数据库。 

2.   外绑定(out-bind):通过INSERTUPDATEDELETE语句的RETURNING子句的返回值为PL/SQL变量或主变量赋值。 

3.   定义(define):使用SELECTFETCH语句为PL/SQL变量或主变量赋值。 

DML语句可以一次性传递集合中所有的元素,这个过程就是批量绑定。如果集合有20个元素,批量绑定的一次操作就相当于执行20SELECTINSERTUPDATEDELETE语句。这项技术是靠减少PL/SQLSQL引擎间的切换次数来提高性能的。要对INSERTUPDATEDELETE语句使用批量绑定,就要用PL/SQLFORALL语句。

如果要在SELECT语句中使用批量绑定,我们就要在SELECT语句后面加上一个BULK COLLECT子句来代替INTO子句。

·        例一:对DELETE语句应用批量绑定 

下面的DELETE语句只往SQL引擎中发送一次,即使是执行了三次DELETE操作:


Declare
  Type numlist Is Varray(20) Of Number;

  depts numlist := numlist(10, 30, 70); -- department numbers
Begin
  Forall i In depts.First .. depts.Last
    Delete From emp Where deptno = depts(i);
End;

·        例二:对INSERT语句应用批量绑定 

下例中,我们把5000个零件编号和名称放到索引表中。所有的表元素都向数据库插入两次:第一次使用FOR循环,然后使用FORALL语句。实际上,FORALL版本的代码执行速度要比FOR语句版本的快得多。

Set serveroutput On;
Create table parts(pnum Number(4), pname Char(15));

Declare
  Type numtab Is Table Of Number(4) Index By Binary_Integer;
  Type nametab Is Table Of Char(15) Index By Binary_Integer;
  pnums  numtab;
  pnames nametab;
  t1     Number;
  t2     Number;
  t3     Number;

Begin
  For j In 1 .. 5000 Loop
    -- load index-by tables
    pnums(j) := j;
    pnames(j) := 'Part No. ' || to_char(j);
  End Loop;
  t1 := dbms_utility.get_time;
  For i In 1 .. 5000 Loop
    -- use FOR loop
    Insert Into parts Values (pnums(i), pnames(i));
  End Loop;
  t2 := dbms_utility.get_time;
  Forall i In 1 .. 5000 -- use FORALL statement
    Insert Into parts Values (pnums(i), pnames(i));
  t3 := dbms_utility.get_time;
  dbms_output.put_line('Execution Time (secs)');
  dbms_output.put_line('---------------------');
  dbms_output.put_line('FOR loop: ' || to_char(t2 - t1));
  dbms_output.put_line('FORALL: ' || to_char(t3 - t2));
End;











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值