como posso atualizar os 100 melhores registros no servidor sql

393

Quero atualizar os 100 principais registros no SQL Server. Eu tenho uma mesa T1com campos F1e F2. T1possui 200 registros. Quero atualizar o F1campo nos 100 melhores registros. Como posso atualizar com base TOP 100no SQL Server?

Rajesh
fonte

Respostas:

684

Observe que os parênteses são necessários para as instruções UPDATE:

update top (100) table1 set field1 = 1
Umair Ahmed
fonte
28
Alguma idéia de como usar o order bytambém?
Joe Phillips
8
@JoePhilllips Use a resposta de Martin Smith para encomendar por
jjxtra
Esses não são os 100 principais registros, no entanto, são simplesmente 100 registros escolhidos arbitrariamente. Os 100 melhores incluiriam alguma ordem para classificar os registros.
precisa saber é o seguinte
11
Isso responde à pergunta "conforme solicitado", mas o TOP não tem sentido (e é imprevisível) sem alguma ORDEM. Veja a resposta mais abaixo de Martin Smith.
Andy G
11
btw: parênteses são importantes!
Simon_Weaver
300

Sem uma ORDER BYidéia toda TOP, não faz muito sentido. Você precisa ter uma definição consistente de qual direção é "para cima" e qual é "para baixo" para que o conceito de topo seja significativo.

No entanto, o SQL Server permite, mas não garante um resultado determinístico .

A UPDATE TOPsintaxe na resposta aceita não suporta uma ORDER BYcláusula, mas é possível obter semântica determinística aqui usando uma CTE ou tabela derivada para definir a ordem de classificação desejada, conforme abaixo.

;WITH CTE AS 
( 
SELECT TOP 100 * 
FROM T1 
ORDER BY F2 
) 
UPDATE CTE SET F1='foo'
Martin Smith
fonte
71
Você diz sem sentido, mas isso não é verdade. Admito que, geralmente / quando você usa TOPprobabilidades, deve usá-las ORDER BYporque o que mais lhe interessa é o "mais" ou o "menos" de alguma coisa. Em outros casos, no entanto, você pode estar interessado apenas em obter um registro correspondente. Como eu hoje! Eu precisava corrigir problemas de dados (ciclos) um de cada vez. Todo o processo de correção envolveu um script db, alguma intervenção do usuário e algumas operações do aplicativo. Não nos importamos com qual disco foi tratado primeiro. Nós apenas nos importávamos que estávamos lidando com eles, um de cada vez.
MetaFight
17
@MetaFight Mas você teria uma WHEREcláusula para excluir registros processados ​​anteriormente. A pergunta como resposta escrita e aceita não tem sentido. BTW: Para o uso de tabelas como uma fila isso é bastante um link útil
Martin Smith
10
Preciso usar top sem ordem para que eu possa executar um processo assíncrono. A cláusula where não incluirá as que já foram processadas, mas só posso processar tantas por vez. Portanto, ele tem um caso de uso perfeitamente válido.
Jeff Davis
4
@ Martin Smith: Digamos que você queira atualizar em lotes, digamos 10000 por vez. Parece ser um bom uso para isso, e a ordem não importa. Como isso "não faz sentido"?
Jay Sullivan
5
@notfed Esse é o mesmo caso que já foi discutido até a morte nos comentários acima. Sua consulta nesse caso não seria semelhante à resposta aceita? Você precisaria de uma wherecláusula para evitar o processamento das mesmas linhas repetidas vezes.
Martin Smith
14

para aqueles como eu ainda presos no SQL Server 2000, SET ROWCOUNT {number};podem ser usados ​​antes da UPDATEconsulta

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

limitará a atualização a 100 linhas

Ele foi preterido pelo menos desde o SQL 2005, mas a partir do SQL 2017 ainda funciona. https://docs.microsoft.com/en-us/sql/t-sql/statements/set-rowcount-transact-sql?view=sql-server-2017

Claudio B
fonte
11
SET ROWCOUNT afeta gatilhos, bem como o comando que está sendo atualizado. Se você tiver um conjunto de exclusão em cascata, poderá ocorrer falha na transação se existir mais do que o número de linhas das linhas filho na tabela filho.
Erici
Com isso dito, SET ROWCOUNT @RowCountParameter; é uma sintaxe válida, enquanto SELECT TOP @RowCountParamter * FROM TableName é inválido. Se você precisar configurar as linhas que estão sendo atualizadas, SET ROWCOUNT # é atualmente a melhor opção, desde que você não tenha tabelas filho com exclusão em cascata ativada.
Erici
No SQL Server 2017, agora é possível usar @variable na cláusula TOP: docs.microsoft.com/en-us/sql/t-sql/queries/…
Alexandr Zarubkin
13
update tb set  f1=1 where id in (select top 100 id from tb where f1=0)
hyyxing
fonte
4

O que é ainda mais interessante é o fato de que você pode usar uma função com valor de tabela embutida para selecionar quais (e quantas via TOP) linha (s) a atualizar. Isso é:

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

Para a função com valor de tabela, você tem algo interessante para selecionar a linha a ser atualizada, como:

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
)

... e aí reside (na minha humilde opinião) o verdadeiro poder de atualizar apenas as principais linhas selecionadas de maneira determinística e ao mesmo tempo simplificar a sintaxe da UPDATEdeclaração.

Michael Goldshteyn
fonte
0

Tentar:

UPDATE Dispatch_Post
SET isSync = 1
WHERE ChallanNo 
IN (SELECT TOP 1000 ChallanNo FROM dbo.Dispatch_Post ORDER BY 
CreatedDate DESC)
Shahin Al Kabir Mitul
fonte
0

Você também pode atualizar de select usando alias e ingressar em:

UPDATE  TOP (500) T
SET     T.SomeColumn = 'Value'
FROM    SomeTable T
        INNER JOIN OtherTable O ON O.OtherTableFK = T.SomeTablePK
WHERE   T.SomeOtherColumn = 1
Vanderlei Pires
fonte