PL/SQL Challenge 每日一题:2013-8-2 SQL%BULK_EXCEPTIONS的填充

[复制链接]
查看11 | 回复3 | 2008-9-15 01:28:12 | 显示全部楼层 |阅读模式
最先答对且答案未经编辑的puber将获得纪念章一枚(答案不可编辑但可发新贴补充或纠正),其他会员如果提供有价值的分析、讨论也可获得纪念章一枚。
以往旧题索引:
http://www.itpub.net/forum.php?m ... eid&typeid=1808
http://www.itpub.net/thread-1499223-1-1.html
原始出处:
http://www.plsqlchallenge.com/
作者:Steven Feuerstein
运行环境:SQLPLUS, SERVEROUTPUT已打开
注:本题给出答案时候要求给予简要说明才能得到奖品
我创建了一个表并填入数据:
CREATE TABLE plch_employees
(
employee_id INTEGER,
last_name VARCHAR2 (100),
salaryNUMBER (8, 0)
)
/
BEGIN
INSERT INTO plch_employees
VALUES (100, 'Ninhursag', 1000000);
INSERT INTO plch_employees
VALUES (200, 'Inanna', 1000000);
INSERT INTO plch_employees
VALUES (300, 'Enlil', 1000000);
COMMIT;
END;
/
然后我写了下列未完成的代码块:
DECLARE
failure_in_forall EXCEPTION;
PRAGMA EXCEPTION_INIT (failure_in_forall, -24381);
TYPE employee_aat IS TABLE OF plch_employees.employee_id%TYPE
INDEX BY PLS_INTEGER;
l_employees employee_aat;
TYPE values_aat IS TABLE OF PLS_INTEGER
INDEX BY PLS_INTEGER;
l_employee_values values_aat;
BEGIN
/*FORALL_HEADER*/
UPDATE plch_employees
SET salary =

salary

* CASE employee_id WHEN 200 THEN 1 ELSE 100 END
WHERE employee_id = l_employees (l_index);
EXCEPTION
WHEN failure_in_forall
THEN
DBMS_OUTPUT.put_line ('Error Indexes:');
FOR indx IN 1 .. SQL%BULK_EXCEPTIONS.COUNT
LOOP
DBMS_OUTPUT.put_line (

SQL%BULK_EXCEPTIONS (indx).ERROR_INDEX);
END LOOP;
ROLLBACK;
END;
/
哪些选项可用来取代/*FORALL_HEADER*/注释,使得代码块执行之后会显示如下文本:
Error Indexes:
1
3
(A)
l_employees (-77) := 100;
l_employees (13067) := 200;
l_employees (1070) := 300;
--
l_employee_values (100) := -77;
l_employee_values (200) := 13067;
l_employee_values (300) := 1070;
FORALL l_index IN VALUES OF l_employee_values
SAVE EXCEPTIONS

(B)
l_employees (1) := 100;
l_employees (2) := 200;
l_employees (3) := 300;
FORALL l_index IN l_employees.FIRST .. l_employees.LAST
SAVE EXCEPTIONS

(C)
l_employees (100) := 100;
l_employees (200) := 200;
l_employees (300) := 300;
FORALL l_index IN l_employees.FIRST .. l_employees.LAST
SAVE EXCEPTIONS

(D)
l_employees (-77) := 100;
l_employees (13067) := 200;
l_employees (1070) := 300;
--
l_employee_values (100) := -77;
l_employee_values (200) := 13067;
l_employee_values (300) := 1070;
FORALL l_index IN VALUES OF l_employee_values


回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
我猜AB
C 的index应该要求是连续的
D 和A相比少了异常保护,这样出了异常就到最后,只会打印一次异常
现在我试下
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
答案AB, 2楼得奖。
A: 我用的是VALUES OF, 既然l_employees集合是稀疏填充的。这没有问题,但是Oracle在 SQL%BULK_EXCEPTIONS 中填充的 ERROR_INDEX并不正确反映绑定数组中的实际索引值。相反,它记录了一组连续数字(1, 然后是3, 因为employee ID=200的UPDATE没有出错)
B: 在这个选项中我的数组是密集填充的,我用的是“经典”的 bind_array.FIRST .. bind_array.LAST格式来指定bind_array的扫描方式。在这种情况下,SQL%BULK_EXCEPTIONS 的填充正如预期般。
C: 这个选项会报错 "ORA-22160: element at index [101] does not exist".
数组是稀疏填充的,我却用了 IN 索引低值..索引高值的格式。
D: 在这种情况下,我用VALUES OF来识别l_employees数组中需要处理的元素,但是我忽略了SAVE EXCEPTIONS选项,所以这个代码块会被这个未处理异常所中断:
ORA-01438: value larger than specified precision allowed for this column

回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
newkid 发表于 2013-8-7 02:52
答案AB, 2楼得奖。
A: 我用的是VALUES OF, 既然l_employees集合是稀疏填充的。这没有问题,但是Oracle在 ...

这个要记住
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行