通常、2 つの異なるクエリを使用して同じテーブルに更新または挿入を実行する必要がある場合があります。これが、マージ ステートメントを使用してテーブルで実行できるかどうかを確認したかったのです。
これができるかどうか知りたいだけです。それ以外の場合は、クエリを更新/挿入操作に個別に分離することに固執する必要があります。
これが私がこれまでに持っているものです:
方法 1:
MERGE INTO TABLEA TARGET
USING (
SELECT 1 FROM DUAL
) SOURCE
ON (TARGET.TARGET.COLA = '001'
AND TARGET.TARGET.COLB = '1111111'
AND TARGET.COLC = '201302'
)
WHEN MATCHED THEN
UPDATE SET TARGET.COLA = '001'
,TARGET.COLB = '1111111'
,TARGET.COLC = '201304'
,TARGET.CREATEDATE = SYSDATE
,TARGET.USERID = 'USERA'
WHEN NOT MATCHED THEN
INSERT (TARGET.COLA
,TARGET.COLB
,TARGET.COLC
,TARGET.COLD
,TARGET.CREATEDATE
,TARGET.USERID)
VALUES('001'
,'1111111'
,'201304'
,'123'
,SYSDATE
,'USERA')
最初は、この方法は理にかなっていました。なぜなら、私は常にソースから結果を返し、それに応じて更新および挿入していたからです。ただし、オラクルはこれに従うことを拒否します。
SQL エラー: ORA-38104: ON 句で参照されている列を更新できません: "TARGET"."EFF_FISCAL_YR_PD_NBR" 38104. 00000 - "ON 句で参照されている列を更新できません: %s" *原因: UPDATE SET の LHS にON句で参照される列
方法 2:
MERGE INTO TABLEA TARGET
USING (
SELECT ROWID AS RID,COLA,COLB,COLC
FROM TABLEA
WHERE COLA = '001'
AND COLB = '1111111'
AND COLC = '201301'
) SOURCE
ON (TARGET.ROWID = SOURCE.RID)
WHEN MATCHED THEN
UPDATE SET TARGET.COLA = '001'
,TARGET.COLB = '1111111'
,TARGET.COLC = '201304'
,TARGET.CREATEDATE = SYSDATE
,TARGET.USERID = 'USERA'
WHEN NOT MATCHED THEN
INSERT (TARGET.COLA
,TARGET.COLB
,TARGET.COLC
,TARGET.COLD
,TARGET.CREATEDATE
,TARGET.USERID)
VALUES('001'
,'1111111'
,'201304'
,'123'
,SYSDATE
,'USERA')
この背後にあるロジックは、ソース テーブルから値を検索しようとして一致した場合、レコードを見つけてそれらの値で更新するというものです。ただし、一致しない場合に挿入しようとすると問題が発生します。ソースがフィルタリングされているため、レコードは返されません。したがって、ターゲットが一致するものは何もなく、何も挿入されません。特に挿入ステートメントには、ソース自体ではなく変数から渡された値によって何も含まれていないため、SOURCE にレコードが見つからない場合 (ターゲットと暗黙的に一致しない場合) に挿入します。
ソースを次のように更新してみました。
SELECT ROWID AS RID,COLA,COLB,COLC
FROM TABLEA
WHERE COLA = '001'
AND COLB = '1111111'
AND COLC = '201301'
UNION ALL
SELECT ROWID,NULL,NULL,NULL FROM DUAL
しかし、これに関する問題は、マージが一致したレコードの更新と、一致しなかったレコードの挿入を行うことです。
私が ROWID を使用している理由を知りたい人のために。これは、(私によるものではありませんが) 設計で、COLA と COLB が結合され、テーブルのインデックスとして使用される主キーになることが示されているためです。COLA、COLB、および COLC の重複は許可されていませんが、フロント エンド インターフェイスを介してすべて更新可能です。ROWID の落とし穴は理解していますが、ターゲットとソースとして 1 つのテーブルのみを使用しているため、テーブルで実行する CRUD 操作に関係なく、ROWID は常にそれ自体に一致します。
概要: 一致するアイテムに対して更新を実行する場合にのみセルフ マージが機能するようになりましたが、挿入が機能しません。