我在插入或更新时尝试在表上使用DML操作。我需要在操作失败时显示列名和列注释。例如代码:
CREATE TABLE test_test(col1 VARCHAR2(10), col2 VARCHAR2(100) not null);
DECLARE
ex_insert_null EXCEPTION;
PRAGMA EXCEPTION_INIT(ex_insert_null, -1400);
ex_value_too_large EXCEPTION;
PRAGMA EXCEPTION_INIT(ex_value_too_large, -12899);
BEGIN
INSERT INTO test_test
(col1
,col2)
SELECT CASE
WHEN LEVEL = 8 THEN
(LEVEL + 1) || 'qqqqqqqqqqqq'
ELSE
(LEVEL + 2) || 'qqq'
END AS col1
,CASE
WHEN LEVEL = 7 THEN
NULL
ELSE
(LEVEL + 3) || 'wwwwwww'
END AS col2
FROM dual
CONNECT BY LEVEL <= 10;
COMMIT;
EXCEPTION
WHEN ex_insert_null THEN
ROLLBACK;
dbms_output.put_line('ex_insert_null at ' || ' ' /* || column_name || ' ' || column_comment */);
WHEN ex_value_too_large THEN
ROLLBACK;
dbms_output.put_line('ex_value_too_large at ' || ' ' /* || column_name || ' ' || column_comment */);
END;
/
答案 0 :(得分:1)
正如APC指出的那样,你可以使用“现有的Oracle异常”,例如,如果你有类似......
procedure insert_( col1 varchar2, col2 varchar2 )
is
v_errorcode varchar2(64) ;
v_errormsg varchar2(128) ;
begin
insert into t ( c1, c2 ) values ( col1, col2 ) ;
exception
when others then
if sqlcode = -1400 or sqlcode = -12899 then
v_errorcode := sqlcode;
v_errormsg := substr( sqlerrm, 1, 128 );
dbms_output.put_line( v_errorcode || ' ' || v_errormsg ) ;
raise;
end if;
end insert_ ;
...您可能会收到错误消息,例如:
-1400 ORA-01400: cannot insert NULL into ("MYSCHEMA"."T"."C2")
-12899 ORA-12899: value too large for column "MYSCHEMA"."T"."C1" (actual: 13, maximum: 10)
如果这对你来说足够了,那很好。但是,您还希望查看列的COMMENTS。虽然我们可以从SQLERRM字符串中获取列名,但使用用户定义的异常可能更可靠(如您所暗示的那样)。
作为起点,以下DDL和PACKAGE代码可能对您有用。 (另见:dbfiddle here)
<强>表格强>
drop table t cascade constraints ;
drop table errorlog cascade constraints ;
create table t (
c1 varchar2(10)
, c2 varchar2(64) not null
) ;
comment on column t.c1 is 'this is the column comment for c1';
comment on column t.c2 is 'this is the column comment for c2';
create table errorlog (
when_ timestamp
, msg varchar2(4000)
) ;
套餐规范
create or replace package P is
-- insert into T, throwing exceptions
procedure insert_( col1 varchar2, col2 varchar2 );
-- use your example SELECT, call the insert_ procedure
procedure insert_test ;
-- retrieve the column comments from user_col_comments
function fetch_comment( table_ varchar2, col_ varchar2 ) return varchar2 ;
end P ;
/
套餐正文
create or replace package body P is
procedure insert_( col1 varchar2, col2 varchar2 )
is
ex_value_too_large exception ; -- T.c1: varchar2(10)
ex_insert_null exception ; -- T.c2: cannot be null
v_errorcol varchar2(32) := '' ;
v_comment varchar2(128) := '' ;
v_tablename constant varchar2(32) := upper('T') ;
begin
if length( col1 ) > 10 then
v_errorcol := upper('C1') ;
raise ex_value_too_large ;
end if;
if col2 is null then
v_errorcol := upper('C2') ;
raise ex_insert_null ;
end if ;
insert into t ( c1, c2 ) values ( col1, col2 ) ;
exception
when ex_value_too_large then
dbms_output.put_line( ' ex_value_too_large @ '
|| v_errorcol || ' (' || fetch_comment( v_tablename, v_errorcol ) || ')' );
when ex_insert_null then
dbms_output.put_line( ' ex_insert_null @ '
|| v_errorcol || ' (' || fetch_comment( v_tablename, v_errorcol ) || ')' );
when others then
raise ;
end insert_ ;
procedure insert_test
is
begin
for rec_ in (
select
case
when level = 8 then ( level + 1 ) || 'qqqqqqqqqqqq'
else ( level + 2 ) || 'qqq'
end as col1
, case
when level = 7 then null
else ( level + 3 ) || 'wwwwwww'
end as col2
from dual
connect by level <= 10
) loop
insert_( rec_.col1, rec_.col2 ) ;
end loop;
commit;
end insert_test;
function fetch_comment( table_ varchar2, col_ varchar2 ) return varchar2
is
v_comment varchar2(4000) ; -- same datatype as in user_tab_comments
begin
select comments into v_comment
from user_col_comments
where table_name = table_
and column_name = col_ ;
return v_comment ;
end fetch_comment ;
end P ;
/
要测试包代码,请执行以下匿名块:
begin
P.insert_test ;
end;
/
-- output
ex_insert_null @ C2 (this is the column comment for c2)
ex_value_too_large @ C1 (this is the column comment for c1)
-- Table T contains:
SQL> select * from T;
C1 C2
3qqq 4wwwwwww
4qqq 5wwwwwww
5qqq 6wwwwwww
6qqq 7wwwwwww
7qqq 8wwwwwww
8qqq 9wwwwwww
11qqq 12wwwwwww
12qqq 13wwwwwww
在dbfiddle中,所有输出将分别写入T和ERRORLOG。如果需要,您还可以使用dbms_output.put_line(在dbfiddle中注释掉)。请注意,insert_test过程中的循环游标效率低(我们可以使用BULK操作)。此外,您需要确定处理异常的位置和方式。如上所述,这个例子只是一个起点 - 可能需要进行大量改进。