2008-09-25 6 views
12

코드가있는 많은 테이블과 긴 ID가있는 설명이 있습니다.오라클 인서트를 통해 하나의 테이블에 행이 없을 수도있는 여러 테이블에서 선택

지금 코드의 숫자를 참조하는 계정 유형에 대한 항목을 만들려면, 그래서 이런 일이 :이 일치하는 경우 tax_status 사람과받는 사람 테이블에서 적절한 값을 검색

insert into account_type_standard (account_type_Standard_id, 
tax_status_id, recipient_id) 
(select account_type_standard_seq.nextval, 
ts.tax_status_id, r.recipient_id 
from tax_status ts, recipient r 
where ts.tax_status_code = ? 
and r.recipient_code = ?) 

해당 코드에 대해 발견됩니다. 불행히도, recipient_code는 Nullable이므로? 대입 값은 null 일 수 있습니다. 물론 암시 적 조인은 행을 반환하지 않으므로 행이 내 테이블에 삽입되지 않습니다.

나는 NVL을 사용해 보았습니다. 및 r.recipient_id에.

r.recipient_code =에서 외부 조인을 강제 실행하려고 시도했습니다. (+)를 추가하여 명시 적 조인이 아니기 때문에 Oracle은 여전히 ​​다른 행을 추가하지 않았습니다.

누구나이 방법을 알고 있습니까?

외부로 recipient_id 조회를 수행 할 수 있도록 명세서를 수정할 수 있습니까? r.recipient_id 대신받는 사람 테이블에서 선택하지 마십시오.하지만이 모든 것을 1 개의 SQL 문에서 수행하는 것을 선호합니다.

답변

22

오라클에 명시 적으로 해당 테이블의 기준과 일치하는 데이터 만 원한다고 말하면 아웃터 조인은 "예상대로"작동하지 않습니다. 이 시나리오에서는 외부 조인이 쓸모 없게 렌더링됩니다.

INSERT INTO account_type_standard 
    (account_type_Standard_id, tax_status_id, recipient_id) 
VALUES( 
    (SELECT account_type_standard_seq.nextval FROM DUAL), 
    (SELECT tax_status_id FROM tax_status WHERE tax_status_code = ?), 
    (SELECT recipient_id FROM recipient WHERE recipient_code = ?) 
) 

[편집] A-를 해결하려면 절 또는 같은 MAX 또는 MIN 등의 집계를 사용하는 경우 각 하위 선택, 추가 할 수 ROWNUM = 1에서 여러 행을 기대합니다. 이것은 물론 모든 경우에 대해 최상의 솔루션이 아닐 수도 있습니다. ts.tax_status_code가 기본 또는 대체 키인지 아닌지 코멘트 당

[편집],

(SELECT account_type_standard_seq.nextval FROM DUAL), 

이 될 수는

account_type_standard_seq.nextval, 
+0

하지 않습니다 이 문제는 tax_status 또는받는 사람에 여러 항목이 있고 NULL받는 사람에게 발생하는 문제입니다. ient_code? –

+0

account_type_standard의 recipient_id 열에 null 수신자 코드 결과가 null로 표시됩니다. 여러 항목에 대해 잘 모릅니다. 그러나 제 경우에는 테이블에 고유 한 코드가 있으므로 괜찮습니다. – Mikezx6r

+0

Tony Andrews에 따르면, 시퀀스 값으로 DUAL에서 선택하지 않아도됩니다. account_type_standard_seq.nextval 만 있으면됩니다. – Mikezx6r

3

이 질문에 나에게 명확하지 않았다. recipient_code와 동일합니다. 이것은 알아두면 유용 할 것입니다.

다음과 같이 OR을 사용하여 바인드 변수가 null 일 가능성을 처리 할 수 ​​있습니다. 첫 번째 두 개의 바인드 변수에 동일한 것을 바인딩합니다.

성능에 대해 우려하는 경우 바인드하려는 값이 null인지 확인한 다음 OR을 피하기 위해 다른 SQL 문을 발행하는 것이 좋습니다.

insert into account_type_standard 
(account_type_Standard_id, tax_status_id, recipient_id) 
(
select 
    account_type_standard_seq.nextval, 
    ts.tax_status_id, 
    r.recipient_id 
from tax_status ts, recipient r 
where (ts.tax_status_code = ? OR (ts.tax_status_code IS NULL and ? IS NULL)) 
and (r.recipient_code = ? OR (r.recipient_code IS NULL and ? IS NULL)) 
+0

이 쿼리는 매우 느릴 가능성이 있습니까? –

+1

예, "성능에 대해 우려하는 경우"에 대한 제 성명 ... –

3

시도 : Oglester의 솔루션의

insert into account_type_standard (account_type_Standard_id, tax_status_id, recipient_id) 
select account_type_standard_seq.nextval, 
     ts.tax_status_id, 
     (select r.recipient_id 
     from recipient r 
     where r.recipient_code = ? 
     ) 
from tax_status ts 
where ts.tax_status_code = ? 
+0

Oglester의 답변보다 효율적인 지 알고 계십니까? 그렇다면이 응답을 받아 들일 수 있습니다. 그렇지 않으면, 나는 각각의 위치에서 모든 선택을하는 것이 from과 where 절을 갖는 것보다 더 분명하다고 생각합니다. 나는 그것이 내가 가진 것임을 압니다. 그러나 ... – Mikezx6r

+0

나는 그것이 훨씬 더 좋다고 (또는 더 나쁘다고) 생각하지 않습니다. 그러나 Oglester의 솔루션에는 DUAL의 선택이 필요하지 않습니다. 수정 된 버전을 표시하는 새로운 대답을 게시했습니다. (단지 * 약간 * 더 효율적 임) –

7

약간 단순화 된 버전은 (순서는 DUAL에서 선택을 필요로하지 않습니다

INSERT INTO account_type_standard 
    (account_type_Standard_id, tax_status_id, recipient_id) 
VALUES( 
    account_type_standard_seq.nextval, 
    (SELECT tax_status_id FROM tax_status WHERE tax_status_code = ?), 
    (SELECT recipient_id FROM recipient WHERE recipient_code = ?) 
) 
-2
insert into received_messages(id, content, status) 
    values (RECEIVED_MESSAGES_SEQ.NEXT_VAL, empty_blob(), ''); 
1
insert into account_type_standard (account_type_Standard_id, tax_status_id, recipient_id) 
select account_type_standard_seq.nextval, 
    ts.tax_status_id, 
    (select r.recipient_id 
    from recipient r 
    where r.recipient_code = ? 
    ) 
from tax_status ts 
where ts.tax_status_code = ? 
+2

코드 응답 만 게시하지 마십시오. – Ren