Actualizar SQL con numeración consecutiva


Quiero actualizar una tabla con numeración consecutiva empezando por 1. La actualización tiene una cláusula where, por lo que solo se renumerarán los resultados que cumplan con la cláusula. ¿Puedo lograr esto eficientemente sin usar una tabla temporal?

Author: Filip De Vos, 2009-07-23

9 answers

Esto probablemente depende de su base de datos, pero aquí hay una solución para MySQL 5 que implica el uso de una variable:

SET @a:=0;
UPDATE table SET field=@a:=@a+1 WHERE whatever='whatever' ORDER BY field2,field3

Probablemente debería editar su pregunta e indicar qué base de datos está utilizando sin embargo.

Editar: Encontré una solución utilizando T-SQL para SQL Server. Es muy similar al método MySQL:

DECLARE @myVar int
SET @myVar = 0

UPDATE
  myTable
SET
  @myvar = myField = @myVar + 1
 45
Author: zombat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-22 20:52:50

Para Microsoft SQL Server 2005/2008. La función ROW_NUMBER () se añadió en 2005.

; with T as (select ROW_NUMBER() over (order by ColumnToOrderBy) as RN
        , ColumnToHoldConsecutiveNumber
    where ...)
update T
set ColumnToHoldConsecutiveNumber = RN

EDITAR: Para SQL Server 2000:

declare @RN int
set @RN = 0 

Update T
set ColumnToHoldConsecutiveNubmer = @RN
    , @RN = @RN + 1
where ...

NOTA: Cuando probé el incremento de @RN parecía suceder antes de configurar la columna a @RN, por lo que lo anterior da números que comienzan en 1.

EDIT: Acabo de notar que aparece que desea crear varios números secuenciales dentro de la tabla. Dependiendo de los requisitos, usted puede ser capaz de hacer esto en un paso único con SQL Server 2005/2008, añadiendo partition by a la cláusula over:

; with T as (select ROW_NUMBER() 
        over (partition by Client, City order by ColumnToOrderBy) as RN
     , ColumnToHoldConsecutiveNumber from TableToUpdate)
update T
set ColumnToHoldConsecutiveNumber = RN
 26
Author: Shannon Severance,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-09 14:10:55

En oracle esto funciona:

update myTable set rowColum = rownum
where something = something else

Http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/pseudocolumns009.htm#i1006297

 2
Author: Jens Schauder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-22 20:10:28

Si desea crear una nueva columna PrimaryKey, use solo esto:

ALTER TABLE accounts ADD id INT IDENTITY(1,1) 
 1
Author: eliashdezr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-23 19:30:43

He utilizado esta técnica durante años para rellenar columnas ordinales y numeradas secuencialmente. Sin embargo, recientemente descubrí un problema con él cuando se ejecuta en SQL Server 2012. Parecería que internamente el motor de consultas está aplicando la actualización utilizando múltiples subprocesos y la porción de predicado de la ACTUALIZACIÓN no se está manejando de una manera segura para subprocesos. Para hacerlo funcionar de nuevo tuve que reconfigurar el grado máximo de paralelismo de SQL Server hasta 1 núcleo.

EXEC sp_configure 'show advanced options', 1;
GO
RECONFIGURE WITH OVERRIDE;
GO
EXEC sp_configure 'max degree of parallelism', 1;
GO
RECONFIGURE WITH OVERRIDE;
GO

DECLARE  @id int
SET @id = -1
UPDATE dbo.mytable
SET @id = Ordinal = @id + 1

Sin esto encuentre que la mayoría de los números secuenciales están duplicados en toda la tabla.

 1
Author: user2412960,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-23 09:35:51

Para que el ejemplo de Shannon funcionara completamente tuve que editar su respuesta:

; WITH CTE AS (
    SELECT ROW_NUMBER() OVER (ORDER BY [NameOfField]) as RowNumber, t1.ID
    FROM [ActualTableName] t1
)
UPDATE [ActualTableName]
    SET Name = 'Depersonalised Name ' + CONVERT(varchar(255), RowNumber)
FROM CTE
    WHERE CTE.Id = [ActualTableName].ID

Como su respuesta estaba tratando de actualizar T, que en su caso era el nombre de la Expresión de Tabla Común, y arroja un error.

 1
Author: Colin Wiseman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-29 20:17:08

Además de usar un CTE o un CON, también es posible usar una actualización con una unión automática a la misma tabla:

UPDATE a
SET a.columnToBeSet = b.sequence
FROM tableXxx a
INNER JOIN
(
   SELECT ROW_NUMBER() OVER ( ORDER BY columnX ) AS sequence, columnY, columnZ
   FROM tableXxx
   WHERE columnY = @groupId AND columnY = @lang2
) b ON b.columnY = a.columnY AND b.columnZ = a.columnZ

La tabla derivada, alias b, se utiliza para generar la secuencia a través de la función ROW_NUMBER() junto con algunas otras columnas que forman una clave primaria virtual. Normalmente, cada fila requerirá un valor de secuencia único.

La cláusula WHERE es opcional y limita la actualización a aquellas filas que cumplen las condiciones especificadas.

La tabla derivada es luego se unió a la misma tabla, alias a, uniéndose en las columnas de clave primaria virtual con la columna que se actualizará establecida en la secuencia generada.

 1
Author: Kevin Swann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-14 11:07:20

¿Unirse a una tabla de números? Implica una mesa extra,pero no sería temporal keep mantendrías la mesa de números alrededor como una utilidad.

Véase http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-numbers-table.html

O

Http://www.sqlservercentral.com/articles/Advanced + Consultas/2547/

(este último requiere un registro gratuito, pero me parece que es una muy buena fuente de consejos y técnicas para MS SQL Servidor, y mucho es aplicable a cualquier implementación SQL).

 0
Author: Val,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-22 20:18:09

es posible, pero solo a través de algunas consultas muy complicadas, básicamente necesita una subconsulta que cuente el número de registros seleccionados hasta ahora, y lo use como ID de secuencia. Escribí algo similar en un momento dado-funcionó, pero fue mucho dolor.

Para ser honesto, sería mejor con una tabla temporal con un campo de autoincremento.

 -1
Author: Daniel Roseman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-22 20:08:51