jak mogę zaktualizować 100 najlepszych rekordów na serwerze SQL


393

Chcę zaktualizować 100 najlepszych rekordów w SQL Server. Mam stolik T1z polami F1i F2. T1ma 200 rekordów. Chcę zaktualizować F1pole w 100 najlepszych rekordach. Jak mogę zaktualizować w oparciu o TOP 100SQL Server?

Odpowiedzi:


684

Uwaga: w instrukcjach UPDATE wymagane są nawiasy:

update top (100) table1 set field1 = 1

28
Masz pomysł, jak z nich korzystać order by?
Joe Phillips

8
@JoePhilllips Skorzystaj z odpowiedzi Martina Smitha, by zamówić
jjxtra,

Nie są to jednak pierwsze 100 rekordów, ale po prostu 100 dowolnie wybranych rekordów. Top 100 zawiera pewną kolejność uszeregowania rekordów.
Thorsten Kettner,

1
Odpowiada to na pytanie „zadane”, ale TOP jest bez znaczenia (i nieprzewidywalny) bez jakiegoś ZAMÓWIENIA. Zobacz odpowiedź poniżej autorstwa Martina Smitha.
Andy G.

1
btw: nawiasy są ważne!
Simon_Weaver,

300

Bez ORDER BYcałej idei TOPnie ma większego sensu. Musisz mieć spójną definicję tego, który kierunek jest „w górę”, a który „w dół”, aby koncepcja góry była znacząca.

Niemniej jednak SQL Server pozwala na to, ale nie gwarantuje wyniku deterministycznego .

UPDATE TOPSkładnia w przyjętym odpowiedź nie obsługuje ORDER BYklauzuli, ale jest możliwe, aby uzyskać deterministyczne semantyki tutaj przy użyciu CTE lub tabelę pochodzącą zdefiniować pożądany porządek jak poniżej.

;WITH CTE AS 
( 
SELECT TOP 100 * 
FROM T1 
ORDER BY F2 
) 
UPDATE CTE SET F1='foo'

71
Mówisz bez znaczenia, ale to nieprawda. Przyznaję, że / zwykle /, kiedy używasz TOPkursów, powinieneś z nich korzystać, ORDER BYponieważ to, co Cię interesuje, jest jak „najbardziej” lub „najmniej” czegoś. W innych przypadkach możesz być zainteresowany uzyskaniem tylko jednego pasującego rekordu. Polub mnie dzisiaj! Musiałem naprawiać problemy z danymi (cyklami) pojedynczo. Cały proces naprawy obejmował skrypt db, interwencję użytkownika i niektóre operacje aplikacji. Nie obchodziło nas, który rekord został obsłużony jako pierwszy. Troszczyliśmy się tylko o to, abyśmy sobie z nimi radzili pojedynczo.
MetaFight

17
@MetaFight Ale wtedy miałbyś WHEREklauzulę wykluczającą wcześniej przetworzone rekordy. Pytanie w formie pisemnej i zaakceptowanej nie ma żadnego znaczenia. BTW: Do używania tabel jako kolejki jest to dość przydatne łącze
Martin Smith,

10
Muszę używać top bez zamówienia, aby móc uruchomić proces asynchroniczny. Klauzula where nie będzie obejmować tych, które zostały już przetworzone, ale mogę przetwarzać tylko tyle naraz. Ma więc doskonale uzasadniony przypadek użycia.
Jeff Davis

4
@Martin Smith: Powiedzmy, że chcesz aktualizować partiami, powiedzmy 10000 naraz. Wydaje się, że jest to przydatne, a kolejność nie ma znaczenia. Jak to „nie ma sensu”?
Jay Sullivan

5
@notfed Jest to ten sam przypadek, co już omówiono na śmierć w powyższych komentarzach. Twoje zapytanie w takim przypadku nie wyglądałoby tak, jak w zaakceptowanej odpowiedzi, prawda? Potrzebujesz whereklauzuli, aby uniknąć ponownego przetwarzania tych samych wierszy.
Martin Smith

14

dla takich jak ja nadal utknąłem z SQL Server 2000, SET ROWCOUNT {number};można użyć przed UPDATEzapytaniem

SET ROWCOUNT 100;
UPDATE Table SET ..;
SET ROWCOUNT 0;

ograniczy aktualizację do 100 wierszy

Jest przestarzałe przynajmniej od SQL 2005, ale od SQL 2017 nadal działa. https://docs.microsoft.com/en-us/sql/t-sql/statements/set-rowcount-transact-sql?view=sql-server-2017


1
SET ROWCOUNT wpływa na wyzwalacze, a także na aktualizowaną komendę. Jeśli masz ustawione usuwanie kaskadowe, transakcja może zakończyć się niepowodzeniem, jeśli w tabeli podrzędnej istnieje więcej niż liczba wierszy wierszy podrzędnych.
Eric,

Powiedziawszy to, ustaw ROWCOUNT @RowCountParameter; jest poprawną składnią, natomiast SELECT TOP @RowCountParamter * FROM TableName jest niepoprawny. Jeśli musisz skonfigurować aktualizowane wiersze, USTAW ROWCOUNT # jest obecnie lepszą opcją, pod warunkiem, że nie masz włączonych tabel potomnych z włączonym kasowaniem kaskadowym.
Eric,

W SQL Server 2017 można teraz używać @variable w klauzuli TOP: docs.microsoft.com/en-us/sql/t-sql/queries/…
Alexandr Zarubkin 24.04.2019

13
update tb set  f1=1 where id in (select top 100 id from tb where f1=0)

4

Co jeszcze fajniejsze, to fakt, że możesz użyć wbudowanej funkcji wycenianej w tabeli, aby wybrać, które (i ile poprzez TOP) wierszy chcesz zaktualizować. To jest:

UPDATE MyTable
SET Column1=@Value1
FROM tvfSelectLatestRowOfMyTableMatchingCriteria(@Param1,@Param2,@Param3)

Dla funkcji wycenianej w tabeli masz coś interesującego, aby wybrać wiersz do aktualizacji, np .:

CREATE FUNCTION tvfSelectLatestRowOfMyTableMatchingCriteria
(
    @Param1 INT,
    @Param2 INT,
    @Param3 INT
)
RETURNS TABLE AS RETURN
(
    SELECT TOP(1) MyTable.*
    FROM MyTable
    JOIN MyOtherTable
      ON ...
    JOIN WhoKnowsWhatElse
      ON ...
    WHERE MyTable.SomeColumn=@Param1 AND ...
    ORDER BY MyTable.SomeDate DESC
)

... i leży (moim skromnym zdaniem) prawdziwa moc aktualizowania tylko wybranych wybranych wierszy deterministycznie, przy jednoczesnym uproszczeniu składni UPDATEinstrukcji.


0

Próbować:

UPDATE Dispatch_Post
SET isSync = 1
WHERE ChallanNo 
IN (SELECT TOP 1000 ChallanNo FROM dbo.Dispatch_Post ORDER BY 
CreatedDate DESC)

0

Możesz także zaktualizować z wyboru za pomocą aliasu i dołączyć:

UPDATE  TOP (500) T
SET     T.SomeColumn = 'Value'
FROM    SomeTable T
        INNER JOIN OtherTable O ON O.OtherTableFK = T.SomeTablePK
WHERE   T.SomeOtherColumn = 1
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.