使用连续编号更新SQL

时间:2009-07-22 20:03:46

标签: sql-server tsql

我想更新一个以1开头的连续编号的表。更新有一个where子句,因此只有满足该子句的结果才会重新编号。我可以在不使用临时表的情况下有效地完成此任务吗?

10 个答案:

答案 0 :(得分:49)

这可能取决于您的数据库,但这是MySQL 5的一个解决方案,涉及使用变量:

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

您应该编辑您的问题并指出您正在使用的数据库。

编辑:我找到了solution利用T-SQL for SQL Server。它与MySQL方法非常相似:

DECLARE @myVar int
SET @myVar = 0

UPDATE
  myTable
SET
  @myvar = myField = @myVar + 1

答案 1 :(得分:28)

对于Microsoft SQL Server 2005/2008。 ROW_NUMBER()函数于2005年添加。

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

编辑:对于SQL Server 2000:

declare @RN int
set @RN = 0 

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

注意:当我测试@RN的增量似乎是在将列设置为@RN之前发生的,所以上面给出了从1开始的数字。

编辑:我刚注意到您希望在表格中创建多个连续数字。根据要求,您可以通过将partition by添加到over子句,在SQL Server 2005/2008的单个过程中执行此操作:

; with T as (select ROW_NUMBER() 
        over (partition by Client, City order by ColumnToOrderBy) as RN
     , ColumnToHoldConsecutiveNumber from TableToUpdate)
update T
set ColumnToHoldConsecutiveNumber = RN

答案 2 :(得分:2)

在oracle中,这有效:

update myTable set rowColum = rownum
where something = something else

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

答案 3 :(得分:2)

UPDATE TableName
SET TableName.id = TableName.New_Id
FROM (
  SELECT id, ROW_NUMBER() OVER (ORDER BY id) AS New_Id
  FROM TableName
  ) TableName

答案 4 :(得分:1)

如果要创建新的主键列,请使用以下命令:

ALTER TABLE accounts ADD id INT IDENTITY(1,1) 

答案 5 :(得分:1)

我已经使用这种技术多年来填充序数和顺序编号的列。但是,我最近在SQL Server 2012上运行时发现了它的一个问题。看起来内部查询引擎正在使用多个线程应用更新,并且UPDATE的谓词部分没有以线程安全的方式处理。为了使其再次工作,我不得不将SQL Server的最大并行度重新配置为1核心。

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

如果没有这个,你会发现大多数序列号在整个表格中都是重复的。

答案 6 :(得分:1)

为了让Shannon完全工作,我必须编辑他的答案:

; 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

因为他的答案是试图更新T,在他的情况下是公用表表达式的名称,它会引发错误。

答案 7 :(得分:1)

除了使用CTE或WITH之外,还可以将具有自联接的更新用于同一个表:

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

派生表别名b用于通过ROW_NUMBER()函数以及形成虚拟主键的其他一些列生成序列。 通常,每行都需要一个唯一的序列值。

WHERE子句是可选的,它将更新限制为满足指定条件的行。

然后,派生表将连接到同一个表,别名a,连接虚拟主键列,并将要更新的列设置为生成的序列。

答案 8 :(得分:0)

加入Numbers表?它涉及一个额外的表,但它不是暂时的 - 你将数字表保存为实用程序。

请参阅http://web.archive.org/web/20150411042510/http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-numbers-table.html

http://www.sqlservercentral.com/articles/Advanced+Querying/2547/

(后者需要免费注册,但我发现它是MS SQL Server的一个非常好的技巧和技术来源,并且很多适用于任何SQL实现)。

答案 9 :(得分:-1)

是可能的,但只能通过一些非常复杂的查询 - 基本上你需要一个子查询来计算到目前为止所选择的记录数,并将其用作序列ID。我曾经在某个方面写过类似的东西 - 它很有效,但这很痛苦。

说实话,你最好使用带有自动增量字段的临时表。