gpt4 book ai didi

sql - 每行或每条语句的 MERGE 语句唯一索引/约束验证?

转载 作者:行者123 更新时间:2023-12-04 14:12:18 24 4
gpt4 key购买 nike

假设我有下表具有以下约束:

create table test as (
select 1 as id, 'a' as name from dual
union all
select 2, 'b' from dual
union all
select 3, 'c' from dual
);

create unique index ind on test(name);

alter table test add constraint constr unique (name);

select * from test;

ID NAME
---------- ----
1 a
2 b
3 c

现在假设我执行以下操作 MERGE :
merge into test t using (
select 4 as id, 'b' as name from dual
union all
select 2 as id, null as name from dual
) s on (s.id = t.id)
when matched then update set t.name = s.name
when not matched then insert(t.id, t.name) values(s.id, s.name)

select * from test;

ID NAME
---------- ----
1 a
2
3 c
4 b

请问以上 MERGE 曾经失败?如果是 UPDATE先是 s,然后是 INSERT s,索引/约束在执行过程中不会失效。但如果它先 INSERT s,然后 UPDATE s,索引将暂时失效并且语句可能会失败?。

有人可以详细解释(或指出正确的方向)Oracle RDBMS 如何处理此类问题?此外,使用 LOG ERRORS INTO 时的处理是否相同?条款?

我问这个问题的主要原因以及为什么我需要一个解决方案:我使用 LOG ERRORS INTO 子句运行了几个小时的 MERGE 语句。错误日志似乎作为一个自治事务工作。一些唯一约束错误(基于唯一索引)在语句完成 upserting 之前就被记录了很长时间(除其他外,我看到序列上升),我不知道为什么(尽管最后,在 upserting 之后,应该没有唯一约束无效)。当我查看 ERROR 表时,我看到 ORA-00001: 在 INSERT 操作中违反了唯一约束 (XXX.YYY)。我可以将 ERROR 表中的这条记录插入到主表中,而不会导致唯一约束失败。所以我想知道为什么首先记录错误。

编辑:下面的答案断言,当执行语句时,约束会在语句的末尾强制执行。我理解并同意(虽然我想了解更多有关此类情况下索引维护的详细信息)。我不明白以及为什么这个问题仍然没有回答是为什么我有这些 ORA-00001:唯一约束 (XXX.YYY) 违反了不应该记录的错误。似乎错误记录机制并没有以原子方式运行。

编辑2:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Solaris: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production

EDIT3:
我玩了一下,并能够重现此错误:
drop table test;

drop table err_test;

create table test as (
select 1 as id, 'a' as name from dual
union all
select 2, 'b' from dual
union all
select 3, 'c' from dual
);

create unique index ind on test(name);

alter table test add constraint constr unique (name);

--select test.rowid, test.* from test;

BEGIN
DBMS_ERRLOG.CREATE_ERROR_LOG (
dml_table_name => 'TEST',
err_log_table_name => 'ERR_TEST');
END;
/

--truncate table err_test;

select * from err_test;

merge /*+ PARALLEL(t 2) */ into test t using (
select 4 as id, 'b' as name from dual
union all
select 2 as id, null as name from dual
) s on (s.id = t.id)
when matched then update set t.name = s.name
when not matched then insert(t.id, t.name) values(s.id, s.name)
LOG ERRORS INTO ERR_TEST('TEST,ID:'||s.id) REJECT LIMIT UNLIMITED;

select * from err_test;

在最后 select * from err_test;我总是得到: ORA-00001: unique constraint (XXX.CONSTR) violated .现在奇怪的是,真正的 MERGE 语句(在生产中)不再在 PARALLEL 中工作,而且有时我仍然会收到此错误...

编辑4:
我已将最佳答案标记为已接受,尽管问题本身并未得到完整回答。看来这只是 Oracle 中的一个错误。

最佳答案

这种合并永远不会失败。

此处通过示例对此进行了解释:Database Concepts - 5. Data Integrity
对于不可延迟的约束(默认):

In a nondeferrable constraint, Oracle Database never defers the validity check of the constraint to the end of the transaction. Instead, the database checks the constraint at the end of each statement. If the constraint is violated, then the statement rolls back.



以上意味着,检查约束 在整个单个 SQL 语句的末尾 ,但不是在执行期间。

下面,在本文档中,您可以找到两个交易示例,它们在“内部”执行期间违反了一些约束规则,但最终它们满足了所有约束,并且是合法的,因为:

... because the database effectively checks constraints after the statement completes. Figure 5-4 shows that the database performs the actions of the entire SQL statement before checking constraints.



最后他们还写道:

The examples in this section illustrate the constraint checking mechanism during INSERT and UPDATE statements, but the database uses the same mechanism for all types of DML statements. The same mechanism is used for all types of constraints, not just self-referential constraints.

关于sql - 每行或每条语句的 MERGE 语句唯一索引/约束验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27398276/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com