INSERT自身内部,关于不合格员工的三个集
合都会被用到;我将把这些集合称为"数据集合"。可以看到,驱动集合与数据集合无需匹配。在学习Oracle数据库10g的新特性时,这是一个关
键点。
结果,清单 2 的行数大约是清单 1行数的2倍,但是清单 2 中的代码会在要求的时间内运行。在使用Oracle数据库10g之前,在这种情况下,
我只会对能够在这一时间内运行代码并开始下一个任务这一点感到高兴。
不过,有了Oracle数据库10g中最新版的PL/SQL,现在我就可以在性能、可读性和代码量方面作出更多的改进。
将VALUES OF用于此过程
在Oracle数据库10g中,可以指定FORALL语句使用的驱动集合中的行的子集。可以使用以下两种方法之一来定义该子集:
将数据集合中的行号与驱动集合中的行号进行匹配。你需要使用INDICES OF子句。
将数据集合中的行号与驱动集合中所定义行中找到的值进行匹配。这需要使用VALUES OF子句。
在对give_raises_in_department进行第二次和最后一次改写中我将使用VALUES OF子句。清单 3 包含这个版本的全部代码。我将略过这一程序
中与前一版本相同的部分。
从声明集合开始,请注意我不再另外定义集合来存放合格的和不合格的员工信息,而是在清单 3 (第17行至第21行)中声明两个"引导"集合:
一个用于符合加薪要求的员工,另一个用于不符合加薪要求的员工。这两个集合的数据类型都是布尔型;不久将会看到,这些集合的数据类型
与FORALL语句毫无关系。FORALL语句只关心定义了哪些行。 在员工表中拥有50 000行信息的give_raises_in_department的三种执行方法的占
用时间 执行方法 用时
CURSOR FOR循环 00:00:38.01
Oracle数据库10g之前的批量处理 00:00:06.09
Oracle数据库10g的批量处理 00:00:02.06
在员工表中拥有100,000行数据的give_raises_in_department的三种执行方法的占用时间 执行方法 用时
CURSOR FOR循环 00:00:58.01
Oracle数据库10g之前的批量处理 00:00:12.00
Oracle数据库10g的批量处理 00:00:05.05
表1:处理50,000行和100,000行数据的用时测试结果
retrieve_employee_info子程序与前面的相同,但是对数据进行划分的方式完全不同(第32行至第44行)。我没有将记录从一个集合复制到另
一个集合(这个操作相对较慢),而只是确定与员工ID集合中的行号相匹配的相应引导集合中的行(通过为其指定一个TRUE值)。
现在可以在两个不同FORALL语句(由第49行和第65行开始)中,将approved_list和denied_list集合用作驱动集合。
为了插入到employee_history表中,我使用了如下语句:
FORALL indx IN VALUES OF denied_list
为了进行更新(给员工进行加薪),我使用这一格式:
FORALL indx IN VALUES OF approved_list
在这两个DML语句中,数据集合是在BULK COLLECT 检索步骤中填充的最初的集合;没有进行过复制。利用VALUES OF,Oracle数据库在这些数据
集合的行中进行筛选,仅使用行号与驱动集合中行号相匹配的行
利用本程序中的VALUES OF,可以避免复制对全部记录进行复制,而是用行号的一个简单列表来替换它们。对于大型数组,进行这些复制的开销
是非常可观的。为了测试Oracle数据库10g的优越性,我装入employee表并对50,000行和100,000行的数据运行测试。为了模拟更多的现实情况
,我将Oracle数据库10g之前的批量处理的执行方法作了修改以进行集合内容的多次复制。然后我使用SQL*Plus SET TIMING ON来显示运行各个
不同的执行方法所用的时间。表 1 给出了结果。
从这些时间测定得到的结论非常清楚:由单个DML语句变为批量处理将大幅缩短耗用时间,数据为50,000行时的用时由38秒减为6秒,数据为
100,000行时的用时由58秒减为12秒。而且,通过使用VALUES OF来避免复制数据,我可以将用时缩短一半左右。
即使没有性能上的改进,VALUES OF及其同类子句--INDICES OF也提高了PL/SQL语言的灵活性,使开发人员能够更轻松地编写出更直观和更容易
维护的代码。
在产品寿命这一点上,PL/SQL是一种成熟且功能强大的语言。因而,其很多新特性都是逐渐增加和改进而成的。不过,这些新特性还是使应用
程序的性能和开发人员的开发效率有了重大改变。VALUES OF就是这种特性的一个很好的例子。