代码之家  ›  专栏  ›  技术社区  ›  Bryan

使用连续编号更新SQL

  •  29
  • Bryan  · 技术社区  · 15 年前

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

    9 回复  |  直到 13 年前
        1
  •  69
  •   zombat    15 年前

    这可能取决于您的数据库,但以下是MySQL 5的解决方案,其中包括使用一个变量:

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

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

    编辑:我找到了一个 solution 将T-SQL用于SQL Server。它与MySQL方法非常相似:

    DECLARE @myVar int
    SET @myVar = 0
    
    UPDATE
      myTable
    SET
      @myvar = myField = @myVar + 1
    
        2
  •  36
  •   Michael Freidgeim    6 年前

    适用于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
    

    编辑:

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

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

    编辑: 我刚刚注意到,您似乎希望在表中创建多个序列号。根据需要,您可以在SQL Server 2005/2008中通过添加 partition by 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
    
        3
  •  4
  •   eliashdezr    12 年前

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

    ALTER TABLE accounts ADD id INT IDENTITY(1,1) 
    
        4
  •  3
  •   Colin Wiseman    8 年前

    为了让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,在他的例子中,T是公共表表达式的名称,它抛出了一个错误。

        5
  •  3
  •   Kevin Swann    7 年前

    除了使用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,联接虚拟主键列,并将要更新的列设置为生成的序列。

        6
  •  2
  •   Jens Schauder    15 年前

    在oracle中,这项工作:

    update myTable set rowColum = rownum
    where something = something else
    

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

        7
  •  2
  •   user2412960    12 年前

    多年来,我一直使用这种技术来填充序数和按顺序编号的列。但是,我最近在SQL Server 2012上运行时发现了一个问题。在内部,查询引擎似乎正在使用多个线程应用更新,并且更新的谓词部分没有以线程安全的方式处理。为了使它再次工作,我必须将SQLServer的最大并行度重新配置为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
    

    如果不这样做,您会发现大多数序列号在整个表中都是重复的。

        8
  •  2
  •   Ravi Sharma    5 年前
    UPDATE TableName
    SET TableName.id = TableName.New_Id
    FROM (
      SELECT id, ROW_NUMBER() OVER (ORDER BY id) AS New_Id
      FROM TableName
      ) TableName
    
        9
  •  0
  •   Community CDub    6 年前

    加入数字表?它涉及到一个额外的表,但它不是临时的——您可以将数字表作为一个实用工具保留。

    看见 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实现)。

        10
  •  -1
  •   Daniel Roseman    15 年前

    信息技术 可能,但只能通过一些非常复杂的查询—基本上,您需要一个子查询来计算迄今为止选择的记录数,并将其用作序列ID。我曾经写过类似的东西—它工作了,但非常痛苦。

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