SQL Server,如何在不丢失数据的情况下创建表后设置自动增量?
我在 SQL Server 2008 中有一个表 table1
,其中有记录.
I have a table table1
in SQL server 2008 and it has records in it.
我希望主键 table1_Sno
列是一个自动递增的列.这可以在不进行任何数据传输或表克隆的情况下完成吗?
I want the primary key table1_Sno
column to be an auto-incrementing column. Can this be done without any data transfer or cloning of table?
我知道我可以使用 ALTER TABLE 添加自动增量列,但是我可以简单地将 AUTO_INCREMENT 选项添加到作为主键的现有列吗?
I know that I can use ALTER TABLE to add an auto-increment column, but can I simply add the AUTO_INCREMENT option to an existing column that is the primary key?
推荐答案
更改 IDENTITY
属性实际上只是元数据更改.但是直接更新元数据需要在单用户模式下启动实例并处理 sys.syscolpars
中的一些列,并且没有记录/不受支持,我不会推荐或将提供任何其他详细信息.
Changing the IDENTITY
property is really a metadata only change. But to update the metadata directly requires starting the instance in single user mode and messing around with some columns in sys.syscolpars
and is undocumented/unsupported and not something I would recommend or will give any additional details about.
对于在 SQL Server 2012+ 上遇到这个答案的人,目前实现自动递增列结果的最简单方法是创建一个 SEQUENCE
对象并设置 next 值for seq
作为列默认值.
For people coming across this answer on SQL Server 2012+ by far the easiest way of achieving this result of an auto incrementing column would be to create a SEQUENCE
object and set the next value for seq
as the column default.
或者,对于以前的版本(从 2005 年开始),解决方法发布在 此连接项 显示了一种完全受支持的方法,无需使用 ALTER TABLE...SWITCH<进行数据操作的大小/代码>.还在 MSDN 上写了博客 此处.虽然实现这个的代码不是很简单,并且有一些限制——比如被改变的表不能成为外键约束的目标.
Alternatively, or for previous versions (from 2005 onwards), the workaround posted on this connect item shows a completely supported way of doing this without any need for size of data operations using ALTER TABLE...SWITCH
. Also blogged about on MSDN here. Though the code to achieve this is not very simple and there are restrictions - such as the table being changed can't be the target of a foreign key constraint.
CREATE TABLE dbo.tblFoo
(
bar INT PRIMARY KEY,
filler CHAR(8000),
filler2 CHAR(49)
)
INSERT INTO dbo.tblFoo (bar)
SELECT TOP (10000) ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM master..spt_values v1, master..spt_values v2
将其更改为具有 identity
列(或多或少是即时的).
Alter it to have an identity
column (more or less instant).
BEGIN TRY;
BEGIN TRANSACTION;
/*Using DBCC CHECKIDENT('dbo.tblFoo') is slow so use dynamic SQL to
set the correct seed in the table definition instead*/
DECLARE @TableScript nvarchar(max)
SELECT @TableScript =
'
CREATE TABLE dbo.Destination(
bar INT IDENTITY(' +
CAST(ISNULL(MAX(bar),0)+1 AS VARCHAR) + ',1) PRIMARY KEY,
filler CHAR(8000),
filler2 CHAR(49)
)
ALTER TABLE dbo.tblFoo SWITCH TO dbo.Destination;
'
FROM dbo.tblFoo
WITH (TABLOCKX,HOLDLOCK)
EXEC(@TableScript)
DROP TABLE dbo.tblFoo;
EXECUTE sp_rename N'dbo.Destination', N'tblFoo', 'OBJECT';
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
PRINT ERROR_MESSAGE();
END CATCH;
测试结果.
INSERT INTO dbo.tblFoo (filler,filler2)
OUTPUT inserted.*
VALUES ('foo','bar')
给予
bar filler filler2
----------- --------- ---------
10001 foo bar
清理
DROP TABLE dbo.tblFoo
相关文章