2016-04-06 3 views
0

私は1つのDBから別のデータベースにCRUDする必要があるシステム統合プロジェクトを持っています。特に複雑ではありません。しかし、ターゲットには存在するがソースにはない行を削除する場合は、少し問題に遭遇しました。標準パターンにはLEFT JOIN、NOT EXISTSまたはNOT INがあります。私はLEFT JOINを選んだ。私の「Phone」テーブルは複合キー、Employee 'Id'、PhoneType:Work、Home、Mobileなどを使用します。標準の左結合により、ソースにないターゲット電話番号はすべて削除されます。これはテーブル全体をクリアします。 注:最終更新以降に変更されたレコードのみを更新します。ターゲット全体ではなく、&ソースです。だから、私は本当に貧しいSQLで私が疑う修正書いた:これは動作しますコンポジットキーではないところでSQLを削除する

-- SOURCE 
DECLARE @tmpPhones TABLE(Id varchar(8), PhoneType int, PhoneNumber varchar(30), PRIMARY KEY (Id, PhoneType)) 
INSERT into @tmpPhones values 
('TEST123', 1, '12345678'), 
('TEST123', 2, '12345678'), 
('TEST123', 3, '12345678') 

-- TARGET 
[email protected] TABLE(Id varchar(8), PhoneType int, PhoneNumber varchar(30), PRIMARY KEY (Id, PhoneType)) 
INSERT into @Phone values 
('TEST123', 1, '12345678'), <-- Exists in both, leave 
('TEST123', 2, '12345678'), <-- Exists in both, leave 
('TEST123', 3, '12345678'), <-- Exists in both, leave 
('TEST123', 4, '12345678'), <-- ONLY delete this one! 
('TEST456', 2, '12345678'), <-- Ignore this employee Id 
('TEST456', 3, '12345678'),  "" 
('TEST456', 4, '12345678')  "" 

DELETE p 
FROM @Phone p 
    LEFT JOIN @tmpPhones t 
    ON t.Id = p.Id AND t.PhoneType = p.PhoneType 
WHERE t.Id IS NULL AND t.PhoneType IS NULL 
    AND p.Id IN (SELECT Id FROM @tmpPhones) <-- a sad hack? 

を、私たちはこれだけの従業員ではなく、他のすべてのレコードを削除していることを確認するためのより良い方法があるような気がします。

提案がありますか?

+0

はこのSQL Serverですか? – Nikki9696

+0

はい、SQL Server 2012. –

+0

LEFT JOINは完全に間違っています – wildplasser

答えて

2

existsを使用してください。

DELETE p 
FROM @Phone p 
where exists (select 1 from @tmpPhones where Id = p.Id) 
AND not exists (select 1 from @tmpPhones where PhoneType = p.PhoneType) 

編集:cteを使用して削除します。

with todelete as (
    select id,phonetype from phone 
    except 
    select id,phonetype from tmpphones t 
    where exists (select 1 from phone where id = t.id) 
    ) 
delete from phone 
where exists (select 1 from todelete where phone.id = id and phone.phonetype = phonetype) 
+0

これはサンプルコードで実行されませんでしたか?他のすべての従業員の電話番号を削除しませんか? selectでチェックすると、id = TEST456で削除したくないものが返されます(セットに複数の従業員IDがある場合、編集は機能しません) – Nikki9696

+0

私のサンプルの最初のものデータ。それは私のハックよりも速いのかどうかは分かりませんが、証明書はもっと正当なものに見えます。どうもありがとう! –

0

マージが正常に動作しているようだ - しかし、あなたはまだidはあなたの参照セットであるかどうかを確認する必要があり、私はその

MERGE @Phone AS TGT 
USING (
SELECT * FROM @tmpPhones 
) AS SRC 
ON TGT.ID=SRC.ID AND TGT.PHONETYPE=SRC.PHONETYPE 
WHEN NOT MATCHED BY SOURCE AND tgt.id IN (SELECT id FROM @tmpPhones) THEN DELETE; 
1

の周りにきれいな方法が表示されていない私は、2つの文が存在していると思いますあなたがそれを説明するように、ほとんどのロジックをキャプチャします。

DELETE p 
FROM @Phone p 
WHERE EXISTS (SELECT 1 FROM @tmpPhone t WHERE t.id = p.id) AND 
     NOT EXISTS (SELECT 1 FROM @tmpPhone t WHERE t.id = p.id AND t.PhoneType = p.PhoneType) ; 
+0

はい、これは完全に動作します。同上。ゴードンに感謝します。あまりにも長い間問題を見つめ、あなたは新鮮な目を求めなければなりません。 –

関連する問題