PL/SQL 异常处理
Posted
技术标签:
【中文标题】PL/SQL 异常处理【英文标题】:PL/SQL exception handling 【发布时间】:2016-01-22 07:11:28 【问题描述】:我是 pl/sql 编程的新手,过去 2 小时一直在尝试解决这个问题
这是我的代码
CREATE OR REPLACE PROCEDURE xx_upd_new_code AS
CURSOR c1 IS
SELECT
eite.t_ep_item_ep_id,
bite.main_item
FROM bidw.item@demantra bite,
t_ep_item eite
WHERE bite.item_code = eite.item
AND bite.main_item = bite.old_code
AND bite.current_flag = 1
AND bite.main_item IS NOT NULL;
a1 c1%ROWTYPE;
BEGIN
xx_dbex('Starts.', 'xx_upd_new_code', 'XX');
OPEN c1;
LOOP
FETCH c1 INTO a1;
EXIT WHEN c1%NOTFOUND;
xx_dbex('Item: ' || a1.main_item, 'xx_upd_new_code', 'XX');
UPDATE t_ep_item
SET item = a1.main_item
WHERE t_ep_item_ep_id = a1.t_ep_item_ep_id;
COMMIT;
xx_dbex('Ends.', 'xx_upd_new_code', 'XX');
END LOOP;
EXCEPTION
WHEN OTHERS THEN xx_dbex('Error.', 'xx_upd_new_code', 'XX');
END xx_upd_new_code;
只要出现错误,程序就会结束,但我希望它移至下一项。 xx_debex 是一个存储日志的过程。
我一直在谷歌搜索,我发现我可以写两个异常&如果条件不满足可以引发异常。我试过这个但它会抛出一个错误 必须声明标识符 a 必须声明标识符项
CREATE OR REPLACE PROCEDURE xx_upd_new_code AS
CURSOR c1 IS
SELECT
eite.t_ep_item_ep_id,
bite.main_item
FROM bidw.item@demantra bite,
t_ep_item eite,
items ite
WHERE bite.item_code = eite.item
AND bite.main_item = bite.old_code
AND bite.current_flag = 1
AND bite.main_item IS NOT NULL;
a1 c1%ROWTYPE;
BEGIN
xx_dbex('Starts.', 'xx_upd_new_code', 'XX');
OPEN c1;
LOOP
FETCH c1 INTO a1;
EXIT WHEN c1%NOTFOUND;
IF item != a1.main_item THEN
xx_dbex('Item: ' || a1.main_item, 'xx_upd_new_code', 'XX');
UPDATE t_ep_item
SET item = a1.main_item
WHERE t_ep_item_ep_id = a1.t_ep_item_ep_id;
COMMIT;
xx_dbex('Ends.', 'xx_upd_new_code', 'XX');
ELSE
RAISE a;
END IF;
END LOOP;
EXCEPTION
WHEN a THEN xx_dbex('Error.', 'xx_upd_new_code', 'XX');
WHEN OTHERS THEN NULL;
END xx_upd_new_code;
另外,它被写在某个地方,我可以把它写成两个不同的块
CREATE OR REPLACE PROCEDURE xx_upd_new_code AS
CURSOR c1 IS
SELECT
eite.t_ep_item_ep_id,
bite.main_item
FROM bidw.item@demantra bite,
t_ep_item eite
WHERE bite.item_code = eite.item
AND bite.main_item = bite.old_code
AND bite.current_flag = 1
AND bite.main_item IS NOT NULL;
a1 c1%ROWTYPE;
BEGIN
xx_dbex('Starts.', 'xx_upd_new_code', 'XX');
BEGIN
EXCEPTION
WHEN OTHERS THEN xx_dbex('Error', 'xx_upd_new_code', 'XX');
END;
OPEN c1;
LOOP
FETCH c1 INTO a1;
EXIT WHEN c1%NOTFOUND;
xx_dbex('Item: ' || a1.main_item, 'xx_upd_new_code', 'XX');
UPDATE t_ep_item
SET item = a1.main_item
WHERE t_ep_item_ep_id = a1.t_ep_item_ep_id;
COMMIT;
END LOOP;
EXCEPTION WHEN OTHERS THEN
xx_dbex('END', 'xx_upd_new_code', 'XX');
END xx_upd_new_code;
我还是想不通。
【问题讨论】:
xx_dbex
程序是做什么的?
【参考方案1】:
将光标循环分成两部分/块。第一个将用于调用日志记录过程的部分,另一个将用于更新表的部分。您的代码主体应如下所示:
BEGIN
Open C1;
loop
fetch C1 into A1;
exit when C1%NOTFOUND
BEGIN
xx_dbex('Item: '||a1.main_item ,'xx_upd_new_code', 'XX');
END;
BEGIN
UPDATE t_ep_item
SET item = a1.main_item
where t_ep_item_ep_id=a1.t_ep_item_ep_id;
COMMIT;
xx_dbex('Ends.','xx_upd_new_code', 'XX');
EXCEPTION
WHEN OTHERS THEN
xx_dbex('Ends.','ERROR', 'XX');
END;
END LOOP;
希望你能明白
【讨论】:
【参考方案2】:只需将循环内的语句封装到一个新的 pl/sql 块中,如下所示:
loop
begin
fetch ...
exception
when ...
end;
end loop;
顺便说一句。记录过程应使用pragma_autonomous_transaction
和commit
独立于当前事务结果。
【讨论】:
以上是关于PL/SQL 异常处理的主要内容,如果未能解决你的问题,请参考以下文章