如何解决ORA-00001: 插入 0 行时违反了唯一约束
我正在尝试将 0 行插入具有唯一约束的表中,但我收到 ORA-00001:违反唯一约束...
下面是我用来很好地捕捉问题的 PL/sql 块
declare
l_cnt number;
begin
set transaction isolation level serializable;
select count(*) into l_cnt from test_view;
dbms_output.put_line('count = ' || to_char(l_cnt));
insert into <table>(<columns>)
select <columns> from test_view
log errors ('run1')
reject limit 0
;
dbms_output.put_line('success');
exception
when others then
dbms_output.put_line('ERRROR!');
dbms_output.put_line(sqlerrm);
rollback;
end;
/
这是输出
count = 0
ERRROR!
ORA-00001: unique constraint (<SCHEMA>.<CONSTRAINT>) violated
果然,ERR$_<table>
表中有一条记录...
如果我在插入语句中添加 where 1 = 0
,一切正常,没有插入任何内容。
我仍然不相信我所看到的:)
Oracle Database 12c Standard Edition Release 12.2.0.1.0 - 64bit Production
更新 1
以下示例没有在视图上使用 count(*)
,因为这可能会导致不同的查询计划为插入选择所有必需的值。
declare
l_cnt number;
begin
set transaction isolation level serializable;
insert into testx_table
select * from testx_view d;
select count(*) into l_cnt from testx_table;
dbms_output.put_line('count = ' || to_char(l_cnt));
insert into <table>(<columns>)
select * from testx_view d
log errors ('run2')
reject limit 0;
dbms_output.put_line('success');
exception
when others then
dbms_output.put_line('ERRROR!');
dbms_output.put_line(sqlerrm);
rollback;
end;
/
更新 2
我能够重现这种行为。
CREATE TABLE A(ID NUMBER PRIMARY KEY)
/
CREATE FUNCTION F(ID_ NUMBER) RETURN NUMBER
AS
L_ID NUMBER;
BEGIN
SELECT ID INTO L_ID FROM A WHERE ID = ID_;
RETURN L_ID;
EXCEPTION
WHEN OTHERS THEN
RETURN NULL;
END;
/
BEGIN
DBMS_ERRLOG.CREATE_ERROR_LOG('A');
END;
/
BEGIN
INSERT INTO A VALUES (1);
INSERT INTO A SELECT 1 FROM DUAL WHERE F(1) IS NULL
LOG ERRORS INTO ERR$_A;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(sqlERRM);
END;
/
SELECT * FROM ERR$_A
/
这一切都归结为查询正在从函数内部修改的表。函数抛出 ORA-04091: table A is mutating,trigger/function may not see it
,但代码捕获所有异常并返回 null。
显然,从正在发生变化的表中进行选择是不正确的,必须修复。
而且我很生气,因为我数不清我告诉同事停止使用 exception when others then return null
的次数。这又是一个例子,它完全掩盖了问题,我花了一整天的时间调试它。
解决方法
选择返回 0 行,没关系。
然而,当向表中插入行时,我们实际上是通过一个函数查询同一个表。该函数返回了 ORA-04091: table A is mutating,trigger/function may not see it
,但它在异常块中被捕获并返回了 null
。这导致查询返回行...
永远不要使用exception when others then return null
!!!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。