2009-08-25 2 views
0

Работает следующий сегмент кода T-SQL, но мне интересно, есть ли более умный и/или менее подробный способ выполнить обмен значениями полей между двумя разными строками. (Код имеет жестко закодированные значения PKEY для простоты.)Обмен значениями между двумя строками данных

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: Я использую Sql2k5 специально так 2k8 не вариант.

+0

SQL 2000, 2005 или 2008? Есть несколько интересных трюков в 2k8 вокруг MERGE и OUTPUT, см. Http://sqlblog.com/blogs/adam_machanic/archive/2009/08/24/dr-output-or-how-i-learned-to-stop-worrying -and-love-the-merge.aspx –

ответ

3

Вы могли бы сделать так:

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

Умный трюк; работает до тех пор, пока добавленные значения DisplaySeq не будут превышать пределы типа. –

+0

Очень интересный трюк Гуффа, но я не вижу, что он детерминирован? Например. как вы гарантируете, что значения будут фактически заменены в вызове Update? Есть ли какая-то логика стекирования, от которой вы зависите? –

+0

@psasik: На самом деле это довольно просто. Сначала вы получаете (x + y), тогда вы можете использовать это для вычисления одного значения от другого: x = (x + y) -y и y = (x + y) -x. – Guffa

0

Как это:

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

(предупреждение: пожалуйста, проверить это первое, что я не могу проверить его здесь).

+0

Вы нигде не определили T1, и вы не используете T2 в любом месте ... – Guffa

+0

Yup, hnxs. Должно было быть Т2 в обоих местах. – RBarryYoung

0

Предполагая, что ваша таблица выглядит следующим образом:

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

Тогда это будет делать это для любых двух заданных значений (я тестировал с 2 и 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 

Хитрость заключается в том, чтобы получить как строки только по обе стороны от соединения, и присоединяться к NOT EQUALS.

0

Попробуйте:

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) 
Смежные вопросы