Sql oracle中的错误/异常处理
我想为下面的场景开发一个程序 我有一个源、一个目标和一个错误表。目标表和错误表具有源表中存在的所有字段。但是错误表的所有字段的数据类型都是varchar。错误表没有完整性、外键和其他约束。 错误表还有两个字段:错误号和错误消息 现在,当执行该过程时,若在将任何记录插入目标时出现错误,那个么该记录应该被移动到错误表中。此外,数据库错误代码和错误消息也应记录在错误表字段中,如前所述 我怎样才能制定这样的程序 表架构示例:Sql oracle中的错误/异常处理,sql,oracle,error-handling,plsql,Sql,Oracle,Error Handling,Plsql,我想为下面的场景开发一个程序 我有一个源、一个目标和一个错误表。目标表和错误表具有源表中存在的所有字段。但是错误表的所有字段的数据类型都是varchar。错误表没有完整性、外键和其他约束。 错误表还有两个字段:错误号和错误消息 现在,当执行该过程时,若在将任何记录插入目标时出现错误,那个么该记录应该被移动到错误表中。此外,数据库错误代码和错误消息也应记录在错误表字段中,如前所述 我怎样才能制定这样的程序 表架构示例: source table src(id number
source table
src(id number
,name varchar2(20)
, ... )
target table
tgt(id number
,name varchar2(20) not null
, ... )
error table
err (id varchar2(255)
,name varchar2(255)
, ...
, errno varchar2(255)
, errmsg varchar2(255))
您看过Oracle自己的错误记录功能吗
您看过Oracle自己的错误记录功能吗
执行此操作的过程可能如下所示:
procedure ins_tgt(p_id in number, p_name in varchar2, ...) is
v_errno number; v_errmsg varchar2(2000);
begin
insert into tgt(id, name, ...) values (p_id, p_name, ...);
exception
when others then
/* copy sqlcode and sqlerrm into variables since they can't be used directly in a SQL statement */
v_errno := sqlcode;
v_errmsg := sqlerrm;
insert into err(id, name, errno, errmsg) values (p_id, p_name, v_errno, v_errmsg);
end;
procedure copy_src_tgt is
begin
for s in (select * from src) loop
ins_tgt(s.id, s.name, ...);
end loop;
end;
但是,将数据从一个表复制到另一个表似乎是一种非常低效的方法…执行此操作的过程可能如下所示:
procedure ins_tgt(p_id in number, p_name in varchar2, ...) is
v_errno number; v_errmsg varchar2(2000);
begin
insert into tgt(id, name, ...) values (p_id, p_name, ...);
exception
when others then
/* copy sqlcode and sqlerrm into variables since they can't be used directly in a SQL statement */
v_errno := sqlcode;
v_errmsg := sqlerrm;
insert into err(id, name, errno, errmsg) values (p_id, p_name, v_errno, v_errmsg);
end;
procedure copy_src_tgt is
begin
for s in (select * from src) loop
ins_tgt(s.id, s.name, ...);
end loop;
end;
CREATE OR REPLACE PACKAGE BODY foo_dml IS
PROCEDURE log_err (
p_sqlcode IN NUMBER,
p_sqlerrm IN VARCHAR2,
p_src IN foo%ROWTYPE
) IS
-- inserts the input row to the err log
BEGIN
INSERT INTO err (
errno,
errmsg,
ID,
NAME,
...
) VALUES (
p_sqlcode,
p_sqlerrm,
p_src.id,
p_src.name,
...
);
END;
PROCEDURE copy_to_tgt (
p_src IN foo%ROWTYPE
) IS
-- copies the input row to the tgt table
BEGIN
INSERT INTO
tgt
VALUES
p_src;
EXCEPTION
WHEN OTHERS THEN
log_err( SQLCODE, SQLERRM, p_src );
END;
END;
/
但将数据从一个表复制到另一个表似乎是一种效率低下的可怕方式…David,我认为你发布了错误的链接-我看不出这一链接的相关性?嗯,奇怪。即使是刚才我点击它的时候,它也对我有效。这肯定是一种科技。更正。。。谢谢托尼。大卫,我想你发错链接了-我看不出这一个有什么关联?嗯,奇怪。即使是刚才我点击它的时候,它也对我有效。这肯定是一种科技。更正。。。谢谢,托尼。你使用的是什么版本的Oracle?另外,您能否解释一下,当Oracle提供了几种更优雅的替代方案时,您为什么要使用这种可怕的机制来加载数据?如果您对源数据中的逻辑错误提出疑问,而不是DBMS可以检测到的错误,请查看MERGE语句,例如:您使用的Oracle版本是什么?另外,您能否解释一下,当Oracle提供了几种更优雅的替代方案时,您为什么要使用这种可怕的机制来加载数据?如果您对源数据中的逻辑错误而不是DBMS可以检测到的错误提出疑问,请查看MERGE语句,例如:here:@ammonQ:谢谢您的回答。你能给我一些有效的代码吗?我是pl/sql新手。有效的方法是“插入tgt select*from src where…”,检查where子句中可能出错的所有内容(不允许空值、值太长等)。是的,这可能意味着你必须在陈述中投入大量的精力。。。顺便说一句,如果我的答案有帮助,你可能想投票和/或接受它。要记录错误(实际上从未发生过,但如果你尝试插入tgt就会发生),你可以使用相同的方法:插入错误(…)从src中选择(…,-1,'名称不能为null'),其中name为null;等等@ammonQ:谢谢你的回复。你能给我一些有效的代码吗?我是pl/sql新手。有效的方法是“插入tgt select*from src where…”,检查where子句中可能出错的所有内容(不允许空值、值太长等)。是的,这可能意味着你必须在陈述中投入大量的精力。。。顺便说一句,如果我的答案有帮助,你可能想投票和/或接受它。要记录错误(实际上从未发生过,但如果你尝试插入tgt就会发生),你可以使用相同的方法:插入错误(…)从src中选择(…,-1,'名称不能为null'),其中name为null;等等。@kusosch:谢谢你的回复。这个代码是否有效,然后由ammoQ推荐。@kusosch:谢谢你的回复。这个代码是否有效,然后由ammoQ推荐。
CREATE OR REPLACE PACKAGE BODY foo_dml IS
PROCEDURE log_err (
p_sqlcode IN NUMBER,
p_sqlerrm IN VARCHAR2,
p_src IN foo%ROWTYPE
) IS
-- inserts the input row to the err log
BEGIN
INSERT INTO err (
errno,
errmsg,
ID,
NAME,
...
) VALUES (
p_sqlcode,
p_sqlerrm,
p_src.id,
p_src.name,
...
);
END;
PROCEDURE copy_to_tgt (
p_src IN foo%ROWTYPE
) IS
-- copies the input row to the tgt table
BEGIN
INSERT INTO
tgt
VALUES
p_src;
EXCEPTION
WHEN OTHERS THEN
log_err( SQLCODE, SQLERRM, p_src );
END;
END;
/