Oracle Insert via Sélectionnez parmi plusieurs tables où une table peut ne pas avoir de ligne

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

  •  02-07-2019
  •  | 
  •  

Question

J'ai un certain nombre de tables de valeurs de code contenant un code et une description avec un identifiant long.

Je souhaite maintenant créer une entrée pour un type de compte qui fait référence à un certain nombre de codes. J'ai donc quelque chose comme ceci:

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

Ceci extrait les valeurs appropriées des tables tax_status et destinataire si une correspondance est trouvée pour leurs codes respectifs. Malheureusement, recipient_code est nullable, et donc le? La valeur de substitution pourrait être nulle. Bien entendu, la jointure implicite ne renvoie pas de ligne, donc aucune ligne n'est insérée dans ma table.

J'ai essayé d'utiliser NVL sur le? et sur le r.recipient_id.

J'ai essayé de forcer une jointure externe sur le r.recipient_code =? en ajoutant (+), mais ce n'est pas une jointure explicite, donc Oracle n'a toujours pas ajouté de ligne.

Quelqu'un connaît-il un moyen de le faire?

Je peux évidemment modifier l’instruction de sorte que je recherche en externe le destinataire_id et que je reçoive un? au lieu de r.recipient_id, et ne sélectionnez pas du tout dans la table des destinataires, mais je préférerais faire tout cela dans une instruction SQL.

Était-ce utile?

La solution

Les jointures externes ne fonctionnent pas "comme prévu". dans ce cas, parce que vous avez explicitement dit à Oracle que vous voulez des données uniquement si les critères de cette table correspondent. Dans ce scénario, la jointure externe est rendue inutile.

Une solution de contournement

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

[Modifier] Si vous attendez plusieurs lignes d'une sous-sélection, vous pouvez ajouter ROWNUM = 1 à chaque clause where OU utiliser un agrégat tel que MAX ou MIN. Bien sûr, cela peut ne pas être la meilleure solution pour tous les cas.

[Modifier] Par commentaire,

  (SELECT account_type_standard_seq.nextval FROM DUAL),

peut être juste

  account_type_standard_seq.nextval,

Autres conseils

Une version légèrement simplifiée de la solution d'Oglester (la séquence ne nécessite pas de sélection à partir de 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 = ?)
)

La question ne me permettait pas de savoir si ts.tax_status_code est une clé primaire ou alternative ou non. Même chose avec recipient_code. Ce serait utile de savoir.

Vous pouvez gérer la possibilité que votre variable de liaison soit nulle en utilisant un OU comme suit. Vous lieriez la même chose aux deux premières variables de lien.

Si les performances vous préoccupent, vous feriez mieux de vérifier si les valeurs que vous souhaitez lier sont nulles ou non, puis émettez une instruction SQL différente pour éviter 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))

Essayez:

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(), '');
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top