2012-05-10 2 views
12

私はmainデータベースとreportデータベースを持っており、mainからreportにテーブルを同期する必要があります。Oracle SQLでMERGEを実行すると、SOURCEに一致しない行を更新するにはどうすればよいですか?

ただし、mainデータベースでアイテムが削除された場合は、reportデータベースにIsDeletedフラグを設定するだけです。

これを行うにはどうすればよいでしょうか?私は現在、このように、MERGE文を使用してい

MERGE INTO report.TEST target 
USING (SELECT * FROM main.TEST) source 
    ON (target.ID = source.ID) 
WHEN MATCHED THEN 
    UPDATE SET (target... = source...) 
WHEN NOT MATCHED THEN 
    INSERT (...) VALUES (source...) 
; 

WHEN NOT MATCHED文はmainから私にすべての新しい値を与えるが、私はまた、reportからすべての古い値を更新します。

私はOracle PL/SQLを使用しています。

+0

'main.test'をどの値で更新しますか?あなたはどこから彼らを得るでしょうか? –

+0

行が 'main.test'から削除された場合、対応する' report.test'行は不一致です。不一致の行に対して 'report.test.IsDeleted'フラグを設定したいと思います。 –

+0

根底にあるJOINの結果( 'using(...)')にはその行が含まれないため、これは可能ではないと思います。そのデータはどこから来るべきですか? –

答えて

11

あなたは、私はあなたのMERGE文にこれを統合する方法を知らない別のUPDATE文

UPDATE report.TEST target 
SET is Deleted = 'Y' 
WHERE NOT EXISTS (SELECT 1 
        FROM main.TEST source 
        WHERE source.ID = target.ID); 

でそれを行うことができます。

+0

私はMERGEでこれを行うことができないのは奇妙に思えます。私はこの答えを考えます。 –

+0

もし私が 'OUTER JOIN'をして、' main.testがnullであるところで '更新されれば、それはもう"エレガント "/効率的でしょうか? –

+1

ここに関連する質問がありますhttp://stackoverflow.com/questions/4863960/could-somebody-explain-what-the-merge-statement-really-does-in-oracle、私はそれが外部結合を行うと思う、完全な外部結合ではないので、私はあなたが提案したことがうまくいくとは思わない。 –

4
MERGE INTO target 
USING 
(
    --Source data 
    SELECT id, some_value, 0 deleteMe FROM source 
    --And anything that has been deleted from the source 
    UNION ALL 
    SELECT id, null some_value, 1 deleteMe 
    FROM 
    (
     SELECT id FROM target 
     MINUS 
     SELECT id FROM source 
    ) 
) source 
    ON (target.ID = source.ID) 
WHEN MATCHED THEN 
    --Requires a lot of ugly CASE statements, to prevent updating deleted data 
    UPDATE SET target.some_value = 
     CASE WHEN deleteMe=1 THEN target.some_value ELSE source.some_value end 
    ,isDeleted = deleteMe 
WHEN NOT MATCHED THEN 
    INSERT (id, some_value, isDeleted) VALUES (source.id, source.some_value, 0) 

--Test data 
create table target as 
select 1 ID, 'old value 1' some_value, 0 isDeleted from dual union all 
select 2 ID, 'old value 2' some_value, 0 isDeleted from dual; 

create table source as 
select 1 ID, 'new value 1' some_value, 0 isDeleted from dual union all 
select 3 ID, 'new value 3' some_value, 0 isDeleted from dual; 


--Results: 
select * from target; 

ID SOME_VALUE ISDELETED 
1 new value 1 0 
2 old value 2 1 
3 new value 3 0 
+0

創造的でありがとう!私はこれをやろうとはしませんが、仕事を終わらせます。 –

-1
merge into x as target using y as Source on target.ID = Source.ID 
when not matched by target then insert 
when matched then update 
when not matched by source and target.ID is not null then 
update whatevercolumn = 'isdeleted' ; 
+0

この構文はどこで見つかりましたか? ( 'by target') –

+0

これは私が探しているものですが、@FlorinGhitaが言ったように、この構文はどこにありますか?このMS SQLの構文ですか? –

+6

-1これは[SQL Server merge](http://msdn.microsoft.com/en-us/library/bb510625.aspx)の構文ではありません。[Oracle merge](http://docs.oracle.com/cd /E11882_01/server.112/e26088/statements_9016.htm#SQLRF01606) – user272735

2

次の答えはにあるUSER_IDUSER_NAMEが一致した場合に、このコマンドのチェックはその後、一致しない場合、それは挿入されます、

MERGE INTO YOUR_TABLE d 
USING (SELECT 1 FROM DUAL) m 
    ON (d.USER_ID = '123' AND d.USER_NAME= 'itszaif') 
WHEN NOT MATCHED THEN 
     INSERT (d.USERS_ID, d.USER_NAME) 
     VALUES ('123','itszaif'); 

同じテーブルにデータをマージします。

関連する問題