【问题标题】:Updating fields in sql incrementing by 1 each time每次更新sql中的字段递增1
【发布时间】:2013-10-28 15:30:38
【问题描述】:

我正在尝试构建一个 SQL 查询,该查询将采用一组行并对所有行上的一个字段重新编号,从它们都与会话 ID 匹配的位置开始。

例如 更改前:

SessionID  |  LineNumber  |  LineContents
----------------------------------------------
74666      |  1           | example content
74666      |  2           | some other content
74666      |  3           | another line
74666      |  4           | final line

更改后(用户已删除第 2 行,因此“LineNumber”值已更新以反映新编号(即“第 3 行”现在已变为“第 2 行”等):

SessionID  |  LineNumber  |  LineContents
----------------------------------------------
74666      |  1           | example content
74666      |  2           | another line
74666      |  3           | final line

所以用非正确的语法来反映这一点应该是这样的

i = 0;
UPDATE tbl_name
SET LineNumber = i++;
WHERE SessionID = 74666;

在没有运气的情况下搜索了很多,任何帮助都很棒:)

【问题讨论】:

  • 您使用的是哪个版本的 SQL Server?
  • 什么决定了您的订单?您有 ID 字段或日期字段吗?
  • 我猜你的意思是 i-- 对于 LineNumber 大于已删除记录 LineNumber 的每一行。
  • 这是你的桌子还是你有什么primaryKey或类似的东西?
  • 回复 Gareth D - 是的,我遗漏了一个唯一的 LineNumberID 字段 回复 jpw - SQL server 2012 回复 Suraj - 是的,我遗漏了一个唯一的 LineNumberID 字段

标签: sql sql-server tsql sql-server-2012


【解决方案1】:

使用Row_Number() 函数和CTE

;WITH CTE AS (
  SELECT SessionID, LineNumber, LineContents,
         Row_Number() OVER(PARTITION BY SessionID ORDER BY LineNumber) Rn
  FROM Table1 
)
UPDATE CTE
SET LineNumber = Rn
WHERE SessionID = 74666;

Fiddle Demo

【讨论】:

    【解决方案2】:

    您可以在 UPDATE 语句中使用 ROW_NUMBER (MS SQL) 或 ROWNUM (Oracle) 或类似内容。

    Check this

    Or this

    【讨论】:

      【解决方案3】:

      您有两种主要方法可以做到这一点。

      第一个“低级”方式是这个(SQL Fiddle here):

      DELETE FROM TestTable 
      WHERE SESSIONID = 74666 AND LineNumber = 3;
      
      UPDATE TestTable SET LineNumber = LineNumber-1
      WHERE SESSIONID = 74666 AND LineNumber > 3
      
      select * from TestTable -- check the result
      

      这里我们假设您知道 LineNumber 和 SessionID。

      另一种方法是通过t-SQL Triggers,稍微复杂一点,但如果您不知道要删除的行的相关信息,它会对您有所帮助。试一试。

      【讨论】:

        【解决方案4】:
        CREATE  TABLE Trial (
        --   ID INT,
         SessionID INT , 
         LineNumber INT ,
         LineContent NVARCHAR(100)
        
        )
        
        INSERT  INTO dbo.trial
        VALUES  ( 74666, 1, 'example content' ) ,
                ( 74666, 2, 'some other content' ),
                ( 74666, 4, 'another line' ),
                ( 74666, 5, 'final line' )
        

        您可以最后删除 LineNumber 值,并可以在更新语句中使用该 id 来更新 LineNumbers 的其余部分,例如此处 Linenumber 3 被删除,

           UPDATE dbo.trial SET LineNumber = LineNumber -1 WHERE LineNumber > 3
        

        【讨论】:

          【解决方案5】:

          如果可能的话,我真的倾向于以不同的方式处理这个问题,并动态生成 Linenumber,以避免维护列,例如:

          CREATE TABLE dbo.T 
          (   
              LineNumberID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, 
              SessionID INT NOT NULL,
              LineContents NVARCHAR(MAX) NOT NULL
          );
          GO
          INSERT dbo.T (SessionID, LineContents)
          VALUES 
              (74666, 'example content'),
              (74666, 'some other content'),
              (74666, 'another line'),
              (74666, 'final line');
          GO
          CREATE VIEW dbo.V
          AS
              SELECT  LinenumberID,
                      SessionID,
                      Linenumber = ROW_NUMBER() OVER(PARTITION BY SessionID ORDER BY LinenumberID),
                      LineContents
              FROM    dbo.T;
          GO
          

          在此您的视图为您提供所需的内容,如果我删除如下:

          SELECT  *
          FROM    dbo.V;
          
          DELETE  dbo.V
          WHERE   SessionID = 74666
          AND     Linenumber = 3;
          
          SELECT  *
          FROM    dbo.V;
          

          你得到输出:

          LINENUMBERID    SESSIONID   LINENUMBER  LINECONTENTS
          1               74666       1           example content
          2               74666       2           some other content
          3               74666       3           another line
          4               74666       4           final line
          
          
          LINENUMBERID    SESSIONID   LINENUMBER  LINECONTENTS
          1               74666       1           example content
          2               74666       2           some other content
          4               74666       3           final line
          

          Example on SQL Fiddle

          因此,您无需实际更新字段即可维护您的连续行号字段。当然,这仅在您可以依赖字段(例如CreatedDate 或 ID 列)进行排序时才有效。否则,您将不得不使用触发器来维护它,并按照其他答案中的建议更新语句。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-12-30
            • 1970-01-01
            相关资源
            最近更新 更多