제약

2009-11-19 3 views
5

을 위반하지 않고 두 개의 DB 행 스와핑 나는 테이블 regionkey 있습니다. 이 테이블에는 고유 제한 조건이있는 (region, locale)에 대한 색인이 있습니다.제약

101 MICH DETR 
102 ILLI CHIC 

그리고 내가 함께 바람 그래서 나는 그들 사이에 필드를 (지역, 로케일)을 교체해야합니다 :

101 ILLI CHIC 
102 MICH DETR 

문제는 그 두 가지 기록을 가지고있다 이 지역 및 지역에 고유 인덱스를 위반 순진한 접근 방식은 작동하지 않습니다

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); 

또는 더 통상적으로 하나 개의 문장에서 할 이 하나)

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

어쨌든 하나의 인서트는 암시 적 트랜잭션 하나임 – gbn

+0

보다 조금 빠름, @gbn ;-) – karlgrz

1

BEst 내기는 세 가지 업데이트를 만드는 것입니다. 첫 번째 레코드를 임시 값 집합으로 업데이트하고 두 번째 레코드를 업데이트 한 다음 첫 번째 레코드를 원하는 값으로 다시 업데이트하십시오.

0

당신이 트랜잭션에 포장의 간단한 행위를 시도 몇 가지 의미를 가지고하지 않는 한 일반적으로 제정신 결과를 얻을?

제한 사항을 설정하여 트랜잭션이 끝날 때 제약 조건을 적용 할 수 있다고 생각하지만 제약 조건이 그런 식으로 설정되어 있는지 확신 할 수 없습니다.

+1

명시 적으로 DDL 문인 DISABLE을 사용하지 않으면 SQL Server에 "지연 제약 조건"이 없습니다. – gbn

+0

계몽되었습니다. 감사합니다. – Broam

0

큰 레코드 세트에 대한 안전하지 않을 수 있습니다 한 가지 제안은,과 같이, 두 개의 업데이트 문, 각 레코드를 모두 지역 & 로케일 모두 기록에 ''를 설정하고 실행하는 것입니다 :

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 

내가 말했듯이 이것은 아마도 가장 안전한 방법은 아니지만 작은 데이터 세트에서는 괜찮을 것입니다.

업데이트 : Larry는 첫 번째 UPDATE 문이 UNIQUE 제약 조건을 위반할 것이라고 정확하게 지적했습니다. 첫 번째 업데이트에 대신 다음을 사용하십시오.

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

이렇게하면 중간 영역과 로케일이 각각 고유하거나 고유해야합니다.

+0

같은 문제 - 초기 UPDATE가 지역, 지역의 고유성을 위반합니다. –

+0

당신이 맞아요! 이를 반영하여 답변을 업데이트했습니다. 잘 했어, 래리! – karlgrz