J'ai un certain nombre de tables de valeurs de code qui contiennent un code et une description avec un long identifiant.
Je veux 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 = ?)
Cela récupère 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 peut être nulle. Bien sûr, 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, Oracle n'a donc toujours pas ajouté de ligne.
Quelqu'un sait-il comment faire cela?
Je peux évidemment modifier l'instruction pour que je fasse la recherche de l'ID_cipient en externe, et avoir 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 en 1 instruction SQL.
Les jointures externes ne fonctionnent pas "comme prévu" dans ce cas, car vous avez explicitement indiqué à Oracle que vous ne voulez des données que si les critères de cette table correspondent. Dans ce scénario, la jointure externe est rendue inutile.
Une solution de rechange
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 vous attendez à plusieurs lignes d'une sous-sélection, vous pouvez ajouter ROWNUM = 1 à chaque clause where OR utilisez un agrégat tel que MAX ou MIN. Ce n'est bien sûr pas le 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,
Une version légèrement simplifiée de la solution d'Oglester (la séquence ne nécessite pas de sélection parmi 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 = ?)
)
Essayer:
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 = ?
Il n'était pas clair pour moi dans la question 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 OR comme suit. Vous lieriez la même chose aux deux premières variables de liaison.
Si vous êtes préoccupé par les performances, 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 le OU.
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))
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 = ?