2009-08-25 6 views
0

Le segment de code T-SQL suivant fonctionne, mais je me demande s'il existe une manière plus astucieuse et/ou moins verbeuse d'effectuer l'échange de valeurs de champ entre deux lignes différentes. (Le code a des valeurs de pkey codées en dur pour la simplicité.)Échange de valeurs entre deux lignes de données

BEGIN TRAN; 

declare @swapFormSeqA int; 
declare @swapFormSeqB int; 

SELECT @swapFormSeqA = DisplaySeq 
FROM CustomCatalogForm 
WHERE CustomCatalogFormId = 1; 

SELECT @swapFormSeqB = DisplaySeq 
FROM CustomCatalogForm 
WHERE CustomCatalogFormId = 2; 

UPDATE CustomCatalogForm 
SET DisplaySeq = @swapFormSeqB 
WHERE CustomCatalogFormId = 1; 

UPDATE CustomCatalogForm 
SET DisplaySeq = @swapFormSeqA 
WHERE CustomCatalogFormId = 2; 

COMMIT TRAN; 

EDIT: J'utilise Sql2k5 spécifiquement si 2K8 est pas une option.

+0

SQL 2000, 2005 ou 2008? Il y a quelques astuces intéressantes en 2k8 autour de MERGE et OUTPUT, voir http://sqlblog.com/blogs/adam_machanic/archive/2009/08/24/dr-output-or-how-i-learned-to-stop-worrying -and-love-the-merge.aspx –

Répondre

3

Vous pouvez faire comme ceci:

begin tran 

declare @sum int 

select @sum = sum(DisplaySeq) 
from CustomCatalogForm 
where CustomCatalogFormId in (1,2) 

update CustomCatalogForm 
set DisplaySeq = @sum - DisplaySeq 
where CustomCatalogFormId in (1,2) 

commit tran 
+0

Astuce astucieuse; fonctionne tant que les valeurs DisplaySeq ajoutées ne dépassent pas les limites du type. –

+0

Astuce très intéressante Guffa mais je ne vois pas que c'est déterministe? Par exemple. Comment êtes-vous assuré que les valeurs seront réellement échangées dans l'appel Update? Y a-t-il une logique d'empilement dont vous dépendez? –

+0

@psasik: C'est plutôt simple, en fait. D'abord vous obtenez (x + y), alors vous pouvez l'utiliser pour calculer une valeur de l'autre: x = (x + y) -y et y = (x + y) -x. – Guffa

0

Comme ceci:

UPDATE CustomCatalogForm 
SET DisplaySeq = (SELECT DisplaySeq 
    FROM CustomCatalogForm T2 
    WHERE T2.CustomCatalogFormId = 
     -1*(CustomCatalogForm.CustomCatalogFormId -2) +1 
    ) 
WHERE CustomCatalogFormId IN (1,2); 

(avertissement: s'il vous plaît tester cette première, comme je ne peux pas tester d'ici).

+0

Vous n'avez défini T1 nulle part, et vous n'utilisez T2 nulle part ... – Guffa

+0

Yup, hnxs. Aurait dû être T2 les deux endroits. – RBarryYoung

0

En supposant que votre table ressemble à ceci:

--drop table CustomCatalogForm 
create table CustomCatalogForm 
(
    CustomCatalogFormId int not null 
    ,DisplaySeq char(1) not null 
) 

insert CustomCatalogForm (CustomCatalogFormId, DisplaySeq) 
values (1,'A') 
insert CustomCatalogForm (CustomCatalogFormId, DisplaySeq) 
values (2,'B') 
insert CustomCatalogForm (CustomCatalogFormId, DisplaySeq) 
values (3,'C') 
insert CustomCatalogForm (CustomCatalogFormId, DisplaySeq) 
values (4,'D') 

Ensuite, ce sera le faire pour deux valeurs données (je l'ai testé avec 2 et 3):

select * from CustomCatalogForm 
------------------------------- 
DECLARE 
    @Item1 int 
,@Item2 int 

SET @Item1 = 2 
SET @Item2 = 3 

UPDATE CustomCatalogForm 
set DisplaySeq = ccf2.DisplaySeq 
from CustomCatalogForm ccf 
    inner join (select CustomCatalogFormId, DisplaySeq 
       from CustomCatalogForm 
       where CustomCatalogFormId = @Item1 
       or CustomCatalogFormId = @Item2) ccf2 
    on ccf.CustomCatalogFormId <> ccf2.CustomCatalogFormId 
where ccf.CustomCatalogFormId = @Item1 
    or ccf.CustomCatalogFormId = @Item2 
------------------------------- 
select * from CustomCatalogForm 

L'astuce est d'obtenir à la fois lignes seulement de chaque côté de la jointure, et se joindre sur NOT EQUALS.

0

Essayez ceci:

UPDATE ccf SET 
    DisplaySeq = Case CustomCatalogFormId 
    When 1 Then T2.DisplaySeq 
    When 2 Then T1.DisplaySeq End 
From CustomCatalogForm ccf 
    Join CustomCatalogForm T1 On T1.CustomCatalogFormId = 1 
    Join CustomCatalogForm T2 On T2.CustomCatalogFormId = 2 
Where ccf.CustomCatalogFormId In (1,2) 
Questions connexes