137

我想用递增的数字更新我的 CODE_DEST 列。我有:

CODE_DEST   RS_NOM
null        qsdf
null        sdfqsdfqsdf
null        qsdfqsdf

我想将其更新为:

CODE_DEST   RS_NOM
1           qsdf
2           sdfqsdfqsdf
3           qsdfqsdf

我试过这段代码:

UPDATE DESTINATAIRE_TEMP
SET CODE_DEST = TheId 
FROM (SELECT  Row_Number()   OVER (ORDER BY [RS_NOM]) AS TheId FROM DESTINATAIRE_TEMP)

这不起作用,因为)

我也试过:

WITH DESTINATAIRE_TEMP AS
  (
    SELECT 
    ROW_NUMBER() OVER (ORDER BY [RS_NOM] DESC) AS RN
    FROM DESTINATAIRE_TEMP
  )
UPDATE DESTINATAIRE_TEMP SET CODE_DEST=RN

但这也因为工会而行不通。

如何使用ROW_NUMBER()SQL Server 2008 R2 中的函数更新列?

4

11 回答 11

224

另一种选择

UPDATE x
SET x.CODE_DEST = x.New_CODE_DEST
FROM (
      SELECT CODE_DEST, ROW_NUMBER() OVER (ORDER BY [RS_NOM]) AS New_CODE_DEST
      FROM DESTINATAIRE_TEMP
      ) x
于 2012-11-30T21:48:35.380 回答
88
DECLARE @id INT 
SET @id = 0 
UPDATE DESTINATAIRE_TEMP
SET @id = CODE_DEST = @id + 1 
GO 

试试这个

http://www.mssqltips.com/sqlservertip/1467/populate-a-sql-server-column-with-a-sequential-number-not-using-an-identity/

于 2014-02-04T04:43:49.707 回答
54
With UpdateData  As
(
SELECT RS_NOM,
ROW_NUMBER() OVER (ORDER BY [RS_NOM] DESC) AS RN
FROM DESTINATAIRE_TEMP
)
UPDATE DESTINATAIRE_TEMP SET CODE_DEST = RN
FROM DESTINATAIRE_TEMP
INNER JOIN UpdateData ON DESTINATAIRE_TEMP.RS_NOM = UpdateData.RS_NOM
于 2012-11-30T16:28:57.537 回答
22

您的第二次尝试失败主要是因为您将 CTE 命名为与基础表相同,并使 CTE 看起来好像是递归 CTE,因为它本质上引用了自己。递归 CTE必须具有需要使用UNION ALL集合运算符的特定结构。

相反,您可以为 CTE 指定一个不同的名称,并将目标列添加到其中:

With SomeName As
(
SELECT 
CODE_DEST,
ROW_NUMBER() OVER (ORDER BY [RS_NOM] DESC) AS RN
FROM DESTINATAIRE_TEMP
)
UPDATE SomeName SET CODE_DEST=RN
于 2012-11-30T22:39:16.960 回答
20

这是@Aleksandr Fedorenko 答案的修改版本,添加了 WHERE 子句:

UPDATE x
SET x.CODE_DEST = x.New_CODE_DEST
FROM (
      SELECT CODE_DEST, ROW_NUMBER() OVER (ORDER BY [RS_NOM]) AS New_CODE_DEST
      FROM DESTINATAIRE_TEMP
      ) x
WHERE x.CODE_DEST <> x.New_CODE_DEST AND x.CODE_DEST IS NOT NULL

通过添加 WHERE 子句,我发现后续更新的性能大大提高。Sql Server 似乎会更新该行,即使该值已经存在并且这样做需要时间,因此添加 where 子句使其只是跳过值未更改的行。我不得不说我很惊讶它运行查询的速度有多快。

免责声明:我不是数据库专家,我在我的子句中使用了 PARTITION BY,所以这个查询的结果可能不完全相同。对我来说,有问题的列是客户的付费订单,因此一旦设置该值通常不会改变。

还要确保你有索引,特别是如果你在 SELECT 语句上有 WHERE 子句。当我根据付款状态进行过滤时,过滤索引对我来说非常有用。


我使用 PARTITION 的查询

UPDATE  UpdateTarget
SET     PaidOrderIndex = New_PaidOrderIndex
FROM
(
    SELECT  PaidOrderIndex, SimpleMembershipUserName, ROW_NUMBER() OVER(PARTITION BY SimpleMembershipUserName ORDER BY OrderId) AS New_PaidOrderIndex
    FROM    [Order]
    WHERE   PaymentStatusTypeId in (2,3,6) and SimpleMembershipUserName is not null
) AS UpdateTarget

WHERE UpdateTarget.PaidOrderIndex <> UpdateTarget.New_PaidOrderIndex AND UpdateTarget.PaidOrderIndex IS NOT NULL

-- test to 'break' some of the rows, and then run the UPDATE again
update [order] set PaidOrderIndex = 2 where PaidOrderIndex=3

如果列不可为空,则不需要“IS NOT NULL”部分。


当我说性能提升巨大时,我的意思是在更新少量行时它基本上是瞬时的。使用正确的索引,我能够实现与“内部”查询本身所花费的时间相同的更新:

  SELECT  PaidOrderIndex, SimpleMembershipUserName, ROW_NUMBER() OVER(PARTITION BY SimpleMembershipUserName ORDER BY OrderId) AS New_PaidOrderIndex
    FROM    [Order]
    WHERE   PaymentStatusTypeId in (2,3,6) and SimpleMembershipUserName is not null
于 2016-12-28T07:52:21.920 回答
5

我为我的情况做了这个并且工作了

WITH myUpdate (id, myRowNumber )
AS
( 
    SELECT id, ROW_NUMBER() over (order by ID) As myRowNumber
    FROM AspNetUsers
    WHERE  UserType='Customer' 
 )

update AspNetUsers set EmployeeCode = FORMAT(myRowNumber,'00000#') 
FROM myUpdate
    left join AspNetUsers u on u.Id=myUpdate.id
于 2018-10-01T15:26:45.540 回答
2

就我而言,我添加了一个新列,并想用整个表的 equevilat 记录号对其进行更新

id  name       new_column (ORDER_NUM)
1   Ali        null
2   Ahmad      null
3   Mohammad   null
4   Nour       null
5   Hasan      null
6   Omar       null

我编写了此查询以使用行号填充新列

UPDATE My_Table
SET My_Table.ORDER_NUM  = SubQuery.rowNumber
FROM (
         SELECT id ,ROW_NUMBER() OVER (ORDER BY [id]) AS rowNumber
         FROM My_Table
     ) SubQuery
INNER JOIN My_Table ON
        SubQuery.id = My_Table.id

执行此查询后,我的新列中有 1,2,3,... 数字

于 2021-04-25T06:18:30.840 回答
1

更新光标的简单方法

UPDATE Cursor
SET Cursor.CODE = Cursor.New_CODE
FROM (
  SELECT CODE, ROW_NUMBER() OVER (ORDER BY [CODE]) AS New_CODE
  FROM Table Where CODE BETWEEN 1000 AND 1999
  ) Cursor
于 2013-07-07T12:32:16.507 回答
1

如果表没有关系,只需将所有行号复制到新表中,然后删除旧表并用旧表重命名新表。

Select   RowNum = ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) , * INTO cdm.dbo.SALES2018 from 
(
select * from SALE2018) as SalesSource
于 2019-01-25T11:31:16.877 回答
0

我使用第一次出现的部分更新临时表,其中多个部分可以与序列号相关联。RowId=1 返回我使用部分和序列号加入 tmp 表和数据的第一次出现。

update #Tmp
set 
#Tmp.Amount=@Amount
from 
(SELECT Part, Row_Number()   OVER (ORDER BY [Part]) AS RowId FROM #Tmp
where Sequence_Num=@Sequence_Num
)data
where data.Part=#Tmp.Part
and data.RowId=1
and #Tmp.Sequence_Num=@Sequence_Num
于 2021-06-22T21:46:19.887 回答
-1

我没有运行 ID 来执行“Basheer AL-MOMANI”建议的操作。我做了这样的事情:(加入我自己的桌子,只是为了得到行号)

update T1 set inID = T2.RN
from (select *, ROW_NUMBER() over (order by ID) RN from MyTable) T1
    inner join (select *, ROW_NUMBER() over (order by ID) RN from MyTable) T2 on T2.RN = T1.RN
于 2022-01-24T16:12:59.360 回答