Oracle Insert tramite Select da più tabelle in cui una tabella potrebbe non avere una riga

StackOverflow https://stackoverflow.com/questions/131164

  •  02-07-2019
  •  | 
  •  

Domanda

Ho un numero di tabelle di valori di codice che contengono un codice e una descrizione con un ID lungo.

Ora voglio creare una voce per un tipo di account che faccia riferimento a un numero di codici, quindi ho qualcosa del genere:

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

In questo modo vengono recuperati i valori appropriati dalle tabelle tax_status e recipiente se viene trovata una corrispondenza per i rispettivi codici. Sfortunatamente, recipient_code è nullable, e quindi il? il valore di sostituzione potrebbe essere nullo. Ovviamente, il join implicito non restituisce una riga, quindi una riga non viene inserita nella mia tabella.

Ho provato a usare NVL sul? e su r.recipient_id.

Ho provato a forzare un join esterno su r.recipient_code =? aggiungendo (+), ma non è un join esplicito, quindi Oracle non ha ancora aggiunto un'altra riga.

Qualcuno sa come farlo?

Posso ovviamente modificare l'affermazione in modo da fare la ricerca del recipient_id esternamente e avere un? invece di r.recipient_id, e non selezionarlo affatto dalla tabella dei destinatari, ma preferirei fare tutto questo in 1 istruzione SQL.

È stato utile?

Soluzione

I join esterni non funzionano " come previsto " in quel caso perché hai esplicitamente detto a Oracle che desideri dati solo se quei criteri su quella tabella corrispondono. In quello scenario, il join esterno è reso inutile.

Una soluzione alternativa

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

[Modifica] Se si prevedono più righe da una sottoselezione, è possibile aggiungere ROWNUM = 1 a ciascuna clausola WHERE o utilizzare un aggregato come MAX o MIN. Questa ovviamente potrebbe non essere la soluzione migliore per tutti i casi.

[Modifica] Per commento,

  (SELECT account_type_standard_seq.nextval FROM DUAL),

può essere solo

  account_type_standard_seq.nextval,

Altri suggerimenti

Una versione leggermente semplificata della soluzione di Oglester (la sequenza non richiede una selezione da 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 = ?)
)

Non mi è stato chiaro nella domanda se ts.tax_status_code è una chiave primaria o alternativa o meno. Stessa cosa con recipient_code. Questo sarebbe utile sapere.

Puoi considerare la possibilità che la tua variabile bind sia nulla usando un OR come segue. Assoceresti la stessa cosa alle prime due variabili di associazione.

Se sei preoccupato per le prestazioni, sarebbe meglio verificare se i valori che intendi associare sono nulli o meno e quindi emettere diverse istruzioni SQL per evitare l'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))

Prova:

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 = ?
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 = ?
insert into received_messages(id, content, status)
    values (RECEIVED_MESSAGES_SEQ.NEXT_VAL, empty_blob(), '');
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top