ORA-00001:违反了唯一约束(MYUSER.ADI_PK)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ORA-00001:违反了唯一约束(MYUSER.ADI_PK)相关的知识,希望对你有一定的参考价值。
我有两张桌子,adv_institution
和institution
。 institution
有5000多行,而adv_institution
有1400多行
我想使用Oracle MERGE将记录从adv_institution
回填到institution
。这两个表有大约四个常见的字段,我可以用来回填。
这是我的整个MERGE声明
merge into
adv_institution to_t
using (
select
uni.*,
adv_c.country_cd as con_code_text
from
(
select
institution_cd,
name,
institution_status,
country_cd
from
institution uni
where
uni.institution_status = 'ACTIVE' and
uni.country_cd is not null
group by
institution_cd,
name,
institution_status,
country_cd
order by
name
) uni,
country_cd c_cd,
adv_country adv_c
where
uni.country_cd = c_cd.country_cd and
c_cd.description = adv_c.country_cd
) from_t
on
(
to_t.VENDOR_INSTITUTION_CD = from_t.INSTITUTION_CD or
to_t.INSTITUTION_CD = from_t.NAME
)
WHEN NOT MATCHED THEN INSERT (
to_t.INSTITUTION_CD,
to_t.INSTITUTION_NAME,
to_t.SHORT_NAME,
to_t.COUNTRY_CD,
to_t.NOTE,
to_t.UNIT_TERMINOLOGY,
to_t.COURSE_TERMINOLOGY,
to_t.CLOSED_IND,
to_t.UPDATE_WHO,
to_t.UPDATE_ON,
to_t.CALLISTA_INSTITUTION_CD
)
VALUES (
from_t.NAME,
from_t.NAME,
'',
from_t.con_code_text,
'',
'UNIT',
'COURSE',
'N',
'MYUSER',
SYSDATE,
from_t.institution_cd
);
我得到的错误是
错误报告 - ORA-00001:违反了唯一约束(MYUSER.ADI_PK)
ADI_PK
意味着adv_institution.institution_cd
是主键,它必须是唯一的。
那是因为在WHEN NOT MATCHED THEN INSERT
中有一个插入语句。我将from_t.NAME
插入to_t.INSTITUTION_CD
。
当插入from_t.NAME
时,to_t.INSTITUTION_CD
看起来至少有两次相同的值
但我做了一个小组声明,以确保from_t.NAME
是独一无二的:
(
select
institution_cd,
name,
institution_status,
country_cd
from
institution uni
where
uni.institution_status = 'ACTIVE' and
uni.country_cd is not null
group by
institution_cd,
name,
institution_status,
country_cd
order by
name
) uni
我不确定我是否正确理解了这个问题。我尽我所能,但仍然没有运气。
我认为你的主要问题是分组。
请考虑以下示例:
desc temp_inventory;
Name Type
--------------------- -----------
WAREHOUSE_NO NUMBER(2)
ITEM_NO NUMBER(10)
ITEM_QUANTITY NUMBER(10)
WAREHOUSE_NO ITEM_NO ITEM_QUANTITY
1 1000 100
1 2000 200
1 2000 300
如果我写一个查询,我想仓库_no是唯一的:
select warehouse_no,item_quantity
from temp_inventory
group by warehouse_no,item_quantity
它将返回相同的3行..而不是我想分组..
select warehouse_no,sum(item_quantity)
from temp_inventory
group by warehouse_no
这将使Warehouse_no在这种情况下独一无二!
此外,如果您有VARCHAR2列,则可以使用MAX,MIN作为聚合函数以及group by在查询中创建唯一键。
例:
Select object_type, min(object_name)
from user_objects group by object_type;
这将使object_type唯一并为其返回1个相应的对象名称。
所以请注意,如果有副本,最后将根据聚合函数消除一些记录。
“但我做了一个小组声明,以确保from_t.NAME是独一无二的:”
但是您的查询不会这样做。它产生了一组独特的(institution_cd,name,institution_status,country_cd)
组合。很明显,这样的集合可能包含name
的多次重复,每个不同的country_cd
值。由于您的密钥中有四个元素,因此您几乎可以保证您的集合将多次出现name
。
你可以在ON条件下将其与or
复合,这意味着如果to_t.VENDOR_INSTITUTION_CD = from_t.INSTITUTION_CD
,即使目标表中已存在to_t.INSTITUTION_CD = from_t.NAME
记录,也会触发UNMATCHED逻辑。
问题是MERGE语句是原子的。来自USING子查询的记录集必须包含唯一键。当Oracle在结果集中发现第二次出现相同的name
时,它没有说,我已经合并了其中一个,让我们跳过它。它必须抛出ORA-00001,因为Oracle无法知道哪个记录适用,(institution_cd,name,institution_status,country_cd)
的哪个组合是正确的。
要解决此问题,您需要更改USING查询以生成具有唯一键的结果集。这是您的数据模型,您了解其业务规则,因此您可以正确地重写它。但也许是这样的:
select
name,
max(institution_cd) as institution_cd,
institution_status,
max(country_cd) as country_cd
from (
institution uni
where
uni.institution_status = 'ACTIVE' and
uni.country_cd is not null
group by
name,
institution_status
order by
name
) uni
然后,您可以将MERGE ON子句简化为:
on
(
to_t.INSTITUTION_CD = from_t.NAME
)
在子查询中使用MAX()
是一种不优雅的kludge。我希望你能应用更好的商业规则。
以上是关于ORA-00001:违反了唯一约束(MYUSER.ADI_PK)的主要内容,如果未能解决你的问题,请参考以下文章
Hibernate 两次将数据插入到 Join Table 中,导致 Spring Boot 项目中出现“ORA-00001:违反唯一约束”
java.sql.SQLException: ORA-00001: 违反唯一约束条件 (SCOTT.SYS_C0011456)