2010-10-05 24 views
25

Poniższa kwerenda działa:SQL aktualizacja Top1 wiersz kwerendy

update top(1) ShipBillInfo 
set  shipfirstname='kkk' 
where CustomerId='134'; 

ale to pokazuje błąd, gdy próbuję zamówić za pośrednictwem Id: na przykład:

update top(1) ShipBillInfo 
set  shipfirstname='kkk' 
where CustomerId='134' 
order by 
     OredrGUID desc; 
+0

Niektóre więcej informacji byłoby miły? Informacje o stole? Przykładowe dane? – Tim

Odpowiedz

21

dlaczego nie zrobić:

update ShipBillInfo 
set shipfirstname='kkk' 
where OrderGUID = (select top (1) OrderGUID 
        from ShipBillInfo 
        where CustomerId = 134 
        order by OredrGUID desc) 
+0

Należy pamiętać, że nie obsługuje to współbieżności, więc w przypadku jednoczesnych wywołań może dwukrotnie aktualizować ten sam wiersz – fabriciorissetto

25
With cte as (
select top(1) shipfirtsname 
From ShipBillInfo 
where CustomerId='134' 
order by OredrGUID desc) 
Update cte set shipfirstname='abc'; 
+0

Te działają lepiej podczas łączenia tabel –

+1

Należy zachować ostrożność przy współbieżności na tym ... – ErikE

+0

@EriE Czy chodziło Ci o wielość (1: wiele relacji między tabelami) lub czy naprawdę chodziło o współbieżność (więcej niż jeden użytkownik/połączenie zmieniające ten sam wiersz w tym samym czasie)? – yzorg

6

Thread Safe

W przypadku rozwiązania zabezpieczającego przed wątkami żaden z zaproponowanych rozwiązań nie zadziałał (niektóre wiersze zostały zaktualizowane więcej niż jeden raz, gdy wykonano je w tym samym czasie).

To działało:

UPDATE Account 
SET sg_status = 'A' 
WHERE AccountId = 
(
    SELECT TOP 1 AccountId 
    FROM Account WITH (UPDLOCK) --this makes it thread safe 
    ORDER BY CreationDate 
) 

Jeśli chcesz powrócić jakąś kolumnę zaktualizowanego elementu można umieścić to w swoim oświadczeniu UPDATE: OUTPUT INSERTED.AccountId (między SET i WHERE)