每次更新sql中的字段递增1
Posted
技术标签:
【中文标题】每次更新sql中的字段递增1【英文标题】:Updating fields in sql incrementing by 1 each time 【发布时间】: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 字段 【参考方案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 列)进行排序时才有效。否则,您将不得不使用触发器来维护它,并按照其他答案中的建议更新语句。
【讨论】:
以上是关于每次更新sql中的字段递增1的主要内容,如果未能解决你的问题,请参考以下文章