長いIDのコードと説明を含むコード値テーブルがいくつかあります。
いくつかのコードを参照するアカウントタイプのエントリを作成したいので、次のようにします。
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 = ?)
これにより、それぞれのコードに一致するものが見つかった場合、tax_statusテーブルとrecipientテーブルから適切な値が取得されます。残念ながら、recipient_codeはNULL可能であるため、?置換値はnullになる可能性があります。もちろん、暗黙の結合は行を返さないため、行がテーブルに挿入されません。
私はNVLを使ってみましたか?およびr.recipient_idにあります。
R.recipient_code =?に外部結合を強制しようとしました(+)を追加しますが、明示的な結合ではないため、Oracleはまだ別の行を追加していません。
誰でもこれを行う方法を知っていますか?
ステートメントを変更して、recipient_idを外部で検索し、? r.recipient_idの代わりに、受信者テーブルから選択しないでください。ただし、これをすべて1つのSQLステートメントで実行することをお勧めします。
その場合、Outter結合は「期待どおりに」機能しません。そのテーブルの基準が一致する場合にのみデータが必要であるとOracleに明示的に指示したためです。そのシナリオでは、外部結合は役に立たなくなります。
回避策
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 = ?)
)
[編集]副選択から複数の行が予想される場合は、ROWNUM = 1を各where句に追加できますOR MAXやMINなどの集計を使用します。これはもちろん、すべてのケースに最適なソリューション。
[編集]コメントごと、
(SELECT account_type_standard_seq.nextval FROM DUAL),
ちょうどすることができます
account_type_standard_seq.nextval,
Oglesterのソリューションのわずかに簡略化されたバージョン(シーケンスは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 = ?)
)
試してください:
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 = ?
Ts.tax_status_codeが主キーまたは代替キーであるかどうかは、質問ではわかりませんでした。 recipient_codeについても同様です。これは知っておくと役に立ちます。
次のようにORを使用して、バインド変数がnullになる可能性に対処できます。同じことを最初の2つのバインド変数にバインドします。
パフォーマンスが心配な場合は、バインドする値が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))
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 = ?