2008-09-25 14 views
12

Mam wiele tabel wartości kodów, które zawierają kod i opis o długim identyfikatorze.Oracle Insert via Wybierz z wielu tabel, w których jedna tabela może nie mieć wiersza

teraz chcę utworzyć wpis na typ konta, które odwołuje się do liczby kodów, więc mam coś takiego:

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 = ?) 

ten pobiera odpowiednie wartości z tax_status i biorcy tabelach Jeśli mecz znajduje się dla ich odpowiednich kodów. Niestety, kod_odbiorcy jest zerowy, a zatem? wartość podstawienia może być pusta. Oczywiście niejawne join nie zwraca wiersza, więc wiersz nie zostanie wstawiony do mojego stołu.

Próbowałem używać NVL na? i na r.recipient_id.

Próbowałem wymusić sprzężenie zewnętrzne na r.recipient_code =? przez dodanie (+), ale nie jest to jawne sprzężenie, więc Oracle nadal nie dodaje kolejnego wiersza.

Ktoś wie, jak to zrobić?

Mogę oczywiście zmodyfikować oświadczenie, tak że sprawdzam adres odbiorcy zewnętrznie i mam? zamiast r.recipient_id i wcale nie wybieram z tabeli odbiorcy, ale wolałbym zrobić to wszystko w 1 instrukcji SQL.

Odpowiedz

22

Dołączenia do Outtera nie działają "zgodnie z oczekiwaniami" w tym przypadku, ponieważ wyraźnie poinformowałeś Oracle, że chcesz tylko danych, jeśli te kryteria w tym zestawieniu są zgodne. W tym scenariuszu łączenie zewnętrzne jest bezużyteczne.

obejście

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 = ?) 
) 

[Edytuj] Jeśli oczekujesz wiele wierszy z sub-select, można dodać ROWNUM = 1 do każdego gdzie klauzula lub użyć kruszywo takie jak MAX lub MIN. To oczywiście nie może być najlepszym rozwiązaniem we wszystkich przypadkach.

[Edytuj] na komentarz,

(SELECT account_type_standard_seq.nextval FROM DUAL), 

może być tylko

account_type_standard_seq.nextval, 
+0

nie Will to jest problem, jest wiele wpisów w statusie podatkowym lub odbiorcy i co dzieje się z NULL recip ient_code? –

+0

Po prostu wypróbowałem, a zerowy kod odbiorcy daje null dla kolumny recipient_id na account_type_standard. Nie wiem o wielu wpisach, ale w moim przypadku tabele mają unikalne kody, więc wszystko jest w porządku. – Mikezx6r

+0

Jak na Tony'ego Andrewsa, nie trzeba wybierać z DUAL dla wartości sekwencji. Może po prostu mieć account_type_standard_seq.nextval. – Mikezx6r

3

To nie było dla mnie jasne, w odpowiedzi na pytanie, czy ts.tax_status_code jest kluczem podstawowym lub zastępcy lub nie. To samo z recipient_code. Byłoby to przydatne wiedzieć.

Możesz poradzić sobie z tym, że twoja zmienna wiązania ma wartość NULL, używając OR w następujący sposób. Wiążesz to samo z pierwszymi dwoma zmiennymi wiązania.

Jeśli obawiasz się wydajności, lepiej sprawdzić, czy wartości, które chcesz powiązać, są wartościami null, a następnie wypisać inne instrukcje SQL, aby uniknąć OR.

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

Czy to zapytanie nie może być zbyt wolne? –

+1

Tak, stąd moje zdanie na temat "Jeśli martwisz się wydajnością ..." –

3

Spróbuj:

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

Czy wiesz, czy jest to bardziej efektywne niż odpowiedź Oglestera? Jeśli tak, to można mnie przekonać do przyjęcia tej odpowiedzi. W przeciwnym razie myślę, że posiadanie wszystkich zaznaczeń w ich lokalizacji jest bardziej przejrzyste niż posiadanie długiej klauzuli "od" i "od". Wiem, że to było to, co miałem, ale ... – Mikezx6r

+0

Nie sądzę, że jest znacznie lepiej (lub gorzej). Jednak rozwiązanie Oglester nie wymaga wyboru z DUAL - wysłałem nową odpowiedź, która pokazuje zmodyfikowaną wersję (tylko * nieznacznie * bardziej wydajnie). –

7

Nieco uproszczona wersja rozwiązania Oglester za (sekwencja nie wymaga select z 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

Proszę nie pisać odpowiedzi tylko kodu. – Ren