设为首页 加入收藏

TOP

Oracle的FORALL用法(批量增删改)(二)
2015-11-21 02:09:54 来源: 作者: 【 】 浏览:7
Tags:Oracle FORALL 用法 批量 删改
%TYPE INDEX BY PLS_INTEGER; TYPE hire_date_aat IS TABLE OF employee.hire_date%TYPE INDEX BY PLS_INTEGER; employee_ids employee_aat; salaries salary_aat; hire_dates hire_date_aat; approved_employee_ids employee_aat; denied_employee_ids employee_aat; denied_salaries salary_aat; denied_hire_dates hire_date_aat; PROCEDURE retrieve_employee_info IS BEGIN SELECT employee_id, salary, hire_date BULK COLLECT INTO employee_ids, salaries, hire_dates FROM employee WHERE department_id = dept_in; END; PROCEDURE partition_by_eligibility IS BEGIN FOR indx IN employee_ids.FIRST .. employee_ids.LAST LOOP IF comp_analysis.is_eligible (employee_ids (indx)) THEN approved_employee_ids (indx) := employee_ids (indx); ELSE denied_employee_ids (indx) := employee_ids (indx); denied_salaries (indx) := salaries (indx); denied_hire_dates (indx) := hire_dates (indx); END IF; END LOOP; END; PROCEDURE add_to_history IS BEGIN FORALL indx IN denied_employee_ids.FIRST .. denied_employee_ids.LAST INSERT INTO employee_history (employee_id , salary , hire_date, activity ) VALUES (denied_employee_ids (indx) , denied_salaries (indx) , denied_hire_dates (indx), 'RAISE DENIED' ); END; PROCEDURE give_the_raise IS BEGIN FORALL indx IN approved_employee_ids.FIRST .. approved_employee_ids.LAST UPDATE employee SET salary = newsal WHERE employee_id = approved_employee_ids (indx); END; BEGIN retrieve_employee_info; partition_by_eligibility; add_to_history; give_the_raise; END give_raises_in_department;

扫一眼清单1 和清单2 就会清楚地认识到:改用集合和批量处理方法将增加代码量和复杂性。但是,如果你需要大幅度提升性能,这还是值得

的。下面,我们不看这些代码,我们来看一看当使用FORALL时,用什么来处理CURSOR FOR循环内的条件逻辑。

定义集合类型与集合

在清单 2中,声明段的第一部分(第6行至第11行)定义了几种不同的集合类型,与我将从员工表检索出的列相对应。我更喜欢基于employee%

ROWTYPE来声明一个集合类型,但是FORALL还不支持对某些记录集合的操作,在这样的记录中,我将引用个别字段。所以,我还必须为员工ID、

薪金和雇用日期分别声明其各自的集合。

接下来为每一列声明所需的集合(第13行至第21行)。首先定义与所查询列相对应的集合(第13行至第15行):

employee_ids employee_aat;
salaries salary_aat;
hire_dates hire_date_aat;


然后我需要一个新的集合,用于存放已被批准加薪的员工的ID(第17行):


approved_employee_ids employee_aat;


最后,我再为每一列声明一个集合(第19行至第21行),用于记录没有加薪资格的员工:

denied_employee_ids employee_aat;
denied_salaries salary_aat;
denied_hire_dates hire_date_aat;

深入了解代码

数据结构确定后,我们现在跳过该程序的执行部分(第72行至第75行),了解如何使用这些集合来加速进程。

retrieve_employee_info;
partition_by_eligibility;
add_to_history;
give_the_raise;


我编写此程序使用了逐步细化法(也被称为"自顶向下设计")。所以执行部分不是很长,也不难理解,只有四行,按名称对过程中的每一步进

行了描述。首先检索员工信息(指定部门的所有员工)。然后进行划分,将要加薪和不予加薪的员工区分出来。完成之后,我就可以将那些不

予加薪的员工添加至员工历史表中,对其他员工进行加薪。

以这种方式编写代码使最终结果的可读性大大增强。因而我可以深入到该程序中对我有意义的任何部分。

有了已声明的集合,我现在就可以使用BULK COLLECT来检索员工信息(第23行至第30行)。这一部分有效地替代了CURSOR FOR循环。至此,数

据被加载到集合中。

划分逻辑(第32行至第46行)要求对刚刚填充的集合中的每一行进行检查,看其是否符合加薪条件。如果符合,我就将该员工ID从查询填充的

集合复制到符合条件的员工的集合。如果不符合,则复制该员工ID、薪金和雇用日期,因为这些都需要插入到employee_history表中。

初始数据现在已被分为两个集合,可以将其分别用作两个不同的FORALL语句(分别从第51行和第66行开始)的驱动器。我将不合格员工的集合

中的数据批量插入到employee_history(add_to_history)表中,并通过give_the_raise过程,在employee表中批量更新合格员工的信息。

最后再仔细地看一看add_to_history(第48行至第61行),以此来结束对这个重新编写的程序的分析。FORALL语句(第51行)包含一个IN子句

,它指定了要用于批量INSERT的行号范围。在对程序进行第二次重写的说明中,我将把用于定义范围的集合称为"驱动集合"。但在

add_to_history的这一版本中,我简单地假定: 使用在denied_employee_ids中定义的所有行。在

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇MYSQL基础01(新增,修改,删除) 下一篇oracle归档与非归档模式介绍

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: