我想更新一个以1开头的连续编号的表。更新有一个where子句,因此只有满足该子句的结果才会重新编号。我可以在不使用临时表的情况下有效地完成此任务吗?
答案 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://www.sqlservercentral.com/articles/Advanced+Querying/2547/
(后者需要免费注册,但我发现它是MS SQL Server的一个非常好的技巧和技术来源,并且很多适用于任何SQL实现)。
答案 9 :(得分:-1)
是可能的,但只能通过一些非常复杂的查询 - 基本上你需要一个子查询来计算到目前为止所选择的记录数,并将其用作序列ID。我曾经在某个方面写过类似的东西 - 它很有效,但这很痛苦。
说实话,你最好使用带有自动增量字段的临时表。