¿Cómo puedo actualizar los 100 mejores registros en el servidor SQL

393

Quiero actualizar los 100 mejores registros en SQL Server. Tengo una mesa T1con campos F1y F2. T1Tiene 200 registros. Quiero actualizar el F1campo en los 100 mejores registros. ¿Cómo puedo actualizar basado TOP 100en SQL Server?

Rajesh
fuente

Respuestas:

684

Tenga en cuenta que los paréntesis son obligatorios para las declaraciones de ACTUALIZACIÓN:

update top (100) table1 set field1 = 1
Umair Ahmed
fuente
28
¿Alguna idea de cómo usar order bytambién?
Joe Phillips
8
@JoePhilllips Use la respuesta de Martin Smith para ordenar por
jjxtra
Sin embargo, estos no son los 100 registros principales, sino simplemente 100 registros elegidos arbitrariamente. Los 100 mejores incluirían algún orden para clasificar los registros.
Thorsten Kettner
1
Esto responde a la pregunta "como se le preguntó", pero TOP no tiene sentido (e impredecible) sin algún ORDEN. Ver la respuesta más abajo por Martin Smith.
Andy G
1
por cierto: ¡los paréntesis son importantes!
Simon_Weaver
300

Sin una ORDER BYidea completa TOPno tiene mucho sentido. Debe tener una definición coherente de qué dirección está "arriba" y cuál está "abajo" para que el concepto de arriba sea significativo.

No obstante, SQL Server lo permite pero no garantiza un resultado determinista .

La UPDATE TOPsintaxis en la respuesta aceptada no admite una ORDER BYcláusula, pero aquí es posible obtener una semántica determinista utilizando un CTE o una tabla derivada para definir el orden de clasificación deseado como se muestra a continuación.

;WITH CTE AS 
( 
SELECT TOP 100 * 
FROM T1 
ORDER BY F2 
) 
UPDATE CTE SET F1='foo'
Martin Smith
fuente
71
Dices que no tiene sentido, pero eso no es cierto. Admito que, / usualmente /, cuando estás usando TOPprobabilidades, deberías usarlo ORDER BYporque lo que te interesa es como "lo más" o "menos" de algo. En otros casos, sin embargo, es posible que solo le interese obtener un registro coincidente. ¡Como yo hoy! Necesitaba solucionar problemas de datos (ciclos) uno a la vez. Todo el proceso de reparación involucró un script db, alguna intervención del usuario y algunas operaciones de la aplicación. No nos importó QUÉ registro se manejó primero. Simplemente nos preocupaba que los estuviéramos manejando uno a la vez.
MetaFight
17
@MetaFight Pero entonces habría tenido una WHEREcláusula para excluir registros procesados ​​previamente. La pregunta como respuesta escrita y aceptada carece de sentido. Por cierto: para usar tablas como una cola, este es un enlace bastante útil
Martin Smith
10
Necesito usar top sin orden para poder ejecutar un proceso asincrónico. La cláusula where no incluirá aquellos que ya se han procesado, pero solo puedo procesar tantos a la vez. Por lo tanto, tiene un caso de uso perfectamente válido.
Jeff Davis el
44
@ Martin Smith: Digamos que desea actualizar en lotes, digamos 10000 a la vez. Parece un buen uso para esto, y el orden no importa. ¿Cómo "no tiene sentido"?
Jay Sullivan
55
@notfed Este es el mismo caso que ya se ha discutido hasta la muerte en los comentarios anteriores. Su consulta en ese caso no se parecería a la de la respuesta aceptada, ¿verdad? Necesitaría una wherecláusula para evitar procesar las mismas filas una y otra vez.
Martin Smith
14

para aquellos como yo que todavía estamos atrapados con SQL Server 2000, SET ROWCOUNT {number};se puede usar antes de la UPDATEconsulta

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

limitará la actualización a 100 filas

Ha quedado en desuso al menos desde SQL 2005, pero a partir de SQL 2017 todavía funciona. https://docs.microsoft.com/en-us/sql/t-sql/statements/set-rowcount-transact-sql?view=sql-server-2017

Claudio B
fuente
1
SET ROWCOUNT afecta los desencadenantes y el comando que se actualiza. Si tiene un conjunto de eliminación en cascada, puede fallar la transacción si existe más de la cantidad de filas secundarias en la tabla secundaria.
EricI
Dicho esto, SET ROWCOUNT @RowCountParameter; es una sintaxis válida, mientras que SELECT TOP @RowCountParamter * FROM TableName no es válido. Si necesita configurar las filas que se actualizan, SET ROWCOUNT # es actualmente la mejor opción, siempre que no tenga tablas secundarias con la eliminación en cascada habilitada.
EricI
En SQL Server 2017 ahora es posible usar @variable en la 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
fuente
4

Lo que es aún mejor es el hecho de que puede usar una función en línea con valores de tabla para seleccionar qué (y cuántas TOP) filas (s) actualizar. Es decir:

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

Para la función de valor de tabla, tiene algo interesante para seleccionar la fila para actualizar 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
)

..., y ahí radica (en mi humilde opinión) el verdadero poder de actualizar solo las primeras filas seleccionadas de manera determinista y al mismo tiempo simplificar la sintaxis de la UPDATEdeclaración.

Michael Goldshteyn
fuente
0

Tratar:

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
fuente
0

También puede actualizar desde select usando un alias y unirse:

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
fuente