制約

2009-11-19 21 views
5

に違反することなく、2つのDB行をスワップIテーブルregionkeyを有します。この表には、ユニーク制約を持つ(region、locale)の索引があります。制約

101 MICH DETR 
102 ILLI CHIC 

そして私はと巻き上げるように、私は、それらの間(地域、ロケール)フィールドを交換する必要があります:

101 ILLI CHIC 
102 MICH DETR 

の問題は、私は2つのレコードを持っているということです地域やロケールの一意のインデックスに違反しているため、素朴なアプローチはうまくいかないでしょう。

update regionkey 
    set region='ILLI', locale='CHIC' where areaid = 101; -- FAILS 
update regionkey 
    set region='MICH', locale='DETR' where areaid = 102; 

どうすればいいですか?スワップを作るためのアトミックな方法はありますか?提案?

答えて

8

(あなたは無効にしない限り)あなたは、複数の文を超えるSQL Serverでの制約チェックを延期することはできませんので、あなたは、競合を避けるために持っているか、トランザクション内の(

update 
    regionkey 
set 
    region= CASE areaid WHEN 101 THEN 'ILLI' ELSE 'MICH' END, 
    locale= CASE areaid WHEN 101 THEN 'CHIC' ELSE 'DETR' END 
where 
    areaid IN (101, 102); 

または、より従来1つのステートメントでそれを行いますこの1つ)

update regionkey 
    set region='AAAA', locale='BBBB' where areaid = 101; 
update regionkey 
    set region='MICH', locale='DETR' where areaid = 102; 
update regionkey 
    set region='ILLI', locale='CHIC' where areaid = 101; 

編集:なぜ値を入れ替えないのですか? areaidに何らかの意味がない限り、通常は正常な結果が得られます

update 
    regionkey 
set 
    areaid = 203 - areaid 
where 
    areaid IN (101, 102); 
+0

これは機能するにはちょっと狂っているかもしれません。あなたは彼がそれを取引で包むべきだと思いますか? – Broam

+0

とにかく1つのインサートが暗黙的なトランザクションである – gbn

+0

私より少し速い@gbn ;-) – karlgrz

1

BEstは3つの更新を行うことです。最初のレコードを一時的な値のセットに更新し、2番目のレコードを更新し、最初のレコードを必要な値に再セットアップします。

0

トランザクションで簡単なラッピングを試みましたか?

私は、トランザクションの最後に制約を適用できるように制約を設定することができますが、制約がそのように設定されているかどうかはわかりません。大きなレコードセットの最も安全ではないかもしれない

+1

明示的にDDLステートメントであるDISABLEを使用しない限り、SQL Serverには「遅延制約」はありません – gbn

+0

私は啓発されています、ありがとうございます。 – Broam

0

1つの提案は、両方の領域&ロケールの「」に両方レコードを設定し、これ等2つのUPDATE文、各レコードのいずれかを実行するであろう。

UPDATE 
    regionkey 
SET 
    region = ' ', 
    locale = ' ' 
WHERE 
    areaid in (101,102) 

UPDATE 
    regionkey 
SET 
    region = 'ILLI', 
    locale = 'CHIC' 
WHERE 
    areaid = 101 

UPDATE 
    regionkey 
SET 
    region = 'MICH', 
    locale = 'DETR' 
WHERE 
    areaid = 102 

私が言ったように、これはおそらく最も安全な方法ではありませんが、小さなデータセットでは問題ありません。

UPDATE:Larryは最初のUPDATE文がUNIQUE制約に違反すると正しく指摘しました。

UPDATE 
    regionkey 
SET 
    region = areaid, 
    locale = areaid 
WHERE 
    areaid in (101,102) 

このように、各中間領域とロケールは一意である(または固有でなければならない)。

+0

同じ問題 - 最初のUPDATEは、地域、ロケールのUNIQUEnessに違反します。 –

+0

あなたは正しいです!私はこれを反映するために私の答えを更新しました。いいキャッチ、@ラリー! – karlgrz