2017-12-17 17 views
1

두 테이블, adv_institutioninstitution이 있습니다. adv_institution 내가 institution에서 adv_institution에 레코드를 백 채우기 위해 오라클 MERGE를 사용하려면 1400ORA-00001 : 고유 제약 (MYUSER.ADI_PK)이 위반되었습니다

있는 동안 institution는 5000 개 행이 있습니다. 이 두 테이블에는 백필에 사용할 수있는 주석 약 4 개의 필드가 있습니다. 여기

내 전체 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에는 삽입 문이 있기 때문입니다. 을 to_t.INSTITUTION_CD에 삽입합니다.

(
     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 

내가 이해하지 확신 : from_t.NAME가 같은 값을 가지고 같은 to_t.INSTITUTION_CD

에 삽입하지만 확실히 from_t.NAME를 만들기 위해 그룹 문을했을 때

그것은 고유 한, 두 번 이상 찾습니다 문제가 올바르게 해결되었습니다. 내가 할 수있는 모든 노력을했지만 여전히 운이 없다.

답변

0

귀하의 주요 문제는 그룹으로 생각합니다. 내가 대신이 같은 3 개 행을 반환 할 것

select warehouse_no,item_quantity 
from temp_inventory 
group by warehouse_no,item_quantity 

.. : 나는 warehouse_no은 고유 할 쿼리를 작성하는 경우

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 

예를 아래에

고려하시기 바랍니다 그룹화하고 싶은 그룹을 선택하십시오.

select warehouse_no,sum(item_quantity) 
from temp_inventory 
group by warehouse_no 

이 상황에서 유일무이 한 창고!

또한 VARCHAR2 열이있는 경우 group by와 함께 집계 함수로 MAX, MIN을 사용하여 쿼리에서 고유 한 키를 만들 수 있습니다.

예 : 그것을 위해 개체 이름을 해당 & 수익 만 1 OBJECT_TYPE 고유하게됩니다

Select object_type, min(object_name) 
from user_objects group by object_type; 

.

따라서 복제본이있는 경우 일부 레코드는 집계 함수에 따라 제거됩니다.

0

는 "그러나 나는 확실히 from_t.NAME이 고유하게 그룹 문을했다 :"

하지만 당신의 쿼리는 그렇게하지 않습니다. (institution_cd,name,institution_status,country_cd)의 고유 한 조합 세트를 생성합니다. 분명히 그런 세트는 name의 여러 재발을 포함 할 수 있습니다. 각각의 다른 값은 country_cd입니다. 키에 4 개의 요소가 있으므로 집합에 name이 여러 번 나타날 것이라는 사실이 사실상 보장됩니다. 이미 어디에서 대상 테이블의 레코드 to_t.INSTITUTION_CD = from_t.NAMEto_t.VENDOR_INSTITUTION_CD = from_t.INSTITUTION_CD 비록 경우는 타의 추종을 불허하는 논리를 트리거 의미 ON 조건에서 or

당신 화합물이,.

문제는 MERGE 문이 원자 적입니다. USING 부속 조회에서 오는 레코드 세트에는 고유 키가 있어야합니다. 오라클이 결과 집합에 같은 name이 두 번째 발견되는 경우, 이 이미 병합되었습니다. 건너 뜁니다. 어떤 레코드가 적용되는지 알 수있는 방법이 없기 때문에 ORA-00001을 던져야합니다. (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 

는 그런 다음에 ON 절 병합을 단순화 할 수는 :

on 
(
    to_t.INSTITUTION_CD = from_t.NAME 
) 

서브 쿼리에서 MAX()의 사용은 우아 kludge입니다. 더 나은 비즈니스 규칙을 적용 할 수 있기를 바랍니다.