Oracle では、Oracle がサブクエリの各行に対してベース テーブルの1 行のみを正確に特定できる場合にのみ、サブクエリを更新できます。さらに、分析機能、集計などの使用に関して、追加の制限が適用されます。
あなたの例では、サブクエリの1行がベーステーブルの複数の行を指す可能性があるDISTINCT
ため、Oracleはサブクエリを更新できなくなります。
を削除するDISTINCT
と、一意のインデックスがオンにMATERIAL(item_id)
なっている場合にのみクエリが機能し、テーブルの各行を のPOLINE
最大 1 行にのみ関連付けることができますMATERIAL
。
UPDATE (SELECT a.item_id, a.account_code acct_a,
b.item_id, b.account_code acct_b
FROM bp.poline a, mt.material b
WHERE a.item_id = b.item_id
AND a.account_code IS NOT NULL
AND b.account_code IS NULL)
SET acct_a = acct_b
結合の更新は非常に効率的ですが、いくつかの制限があります。このインデックスがない場合はどうでしょうか?
別のサブクエリを使用して標準の更新を作成できます。
UPDATE poline a
SET a.account_code = (SELECT b.account_code
FROM material b
WHERE b.item_id = a.item_id
AND b.account_code is not null)
WHERE a.account_code IS NULL
AND a.item_id IN (SELECT b.item_id
FROM material b
WHERE b.account_code IS NOT NULL)
ただし、同様の質問への回答に触発された最もエレガントなIMOソリューションは次のとおりです。
MERGE INTO (SELECT * FROM a WHERE account_code IS NULL) a
USING (SELECT * FROM b WHERE account_code IS NOT NULL) b
ON (a.item_id = b.item_id)
WHEN MATCHED THEN UPDATE SET a.account_code = b.account_code;