如何将自动递增功能添加到现有的SQL ID主键?

huangapple go评论69阅读模式
英文:

How do I add Auto Increment to Existing SQL ID Primary Key?

问题

不能将空值插入到列 'ID',表 'DB_9CF886_mcl959.dbo.Posts' 中;该列不允许为空。插入失败。

所以我尝试添加标识:

alter table dbo.Posts ADD ID INT IDENTITY(1,1) CONSTRAINT PK_Posts1 PRIMARY KEY CLUSTERED;

这给了我这个错误:

每个表中的列名必须是唯一的。表 'dbo.Posts' 中的列名 'ID' 被指定了多次。

我可以删除表并重新创建它,但我想知道如何修复它以将标识添加到ID列。

数据库的截图:dbo.Posts

英文:

I have an empty table that I thought was auto increment until I tried adding my first record. That's when SQL told me this:

> Cannot insert the value NULL into column 'ID', table 'DB_9CF886_mcl959.dbo.Posts'; column does not allow nulls. INSERT fails.

So I tried to add the identity to it:

alter table dbo.Posts ADD ID INT IDENTITY(1,1) CONSTRAINT PK_Posts1 PRIMARY KEY CLUSTERED;

That gave me this error:

> Column names in each table must be unique. Column name 'ID' in table 'dbo.Posts' is specified more than once.

I could drop the table and recreate it, but I'd like to know how to FIX IT to add the identity to the ID column.

Screenshot of database: dbo.Posts

答案1

得分: 4

以下是翻译好的部分:

虽然不能将IDENTITY添加到现有列,并且将IDENTITY添加到现有表意味着添加一个新列是正确的,但也可以不使用IDENTITY,也不需要DROP任何内容。

相反,可以使用SEQUENCE对象来修改现有的ID列以获取新值,这与IDENTITY具有(实际上)相同的最终结果,但这样可以保留现有的ID列值,保留外键引用,并保留CLUSTERED索引,而无需重建表格。

请执行以下操作:

SET XACT_ABORT ON;

BEGIN TRANSACTION;

DECLARE @baseId int = ( SELECT ISNULL( MAX( ID ), 0 ) FROM dbo.Posts ) + 1;

-- https://learn.microsoft.com/en-us/sql/t-sql/statements/create-sequence-transact-sql
CREATE SEQUENCE dbo.PostsIdSequence START WITH @baseId INCREMENT BY 1;

ALTER TABLE dbo.Posts
    ADD CONSTRAINT DF_Posts_Sequence DEFAULT NEXT VALUE FOR dbo.PostsIdSequence FOR "ID";

COMMIT TRANSACTION;
英文:

While it's true that you cannot add IDENTITY to an existing column, and that adding IDENTITY to an existing table means adding a new column - it's also true that you don't need to use IDENTITY - nor do you need to DROP anything either.

Instead, ALTER your existing ID column to use a SEQUENCE object for new values - which has (effectively) the same end-result as IDENTITY - but this way it will preserve your existing ID column values, preserve foreign-key references, and preserve your CLUSTERED index without needing a table rebuild.

Do this:

SET XACT_ABORT ON;

BEGIN TRANSACTION;

DECLARE @baseId int = ( SELECT ISNULL( MAX( ID ), 0 ) FROM dbo.Posts ) + 1;

-- https://learn.microsoft.com/en-us/sql/t-sql/statements/create-sequence-transact-sql
CREATE SEQUENCE dbo.PostsIdSequence START WITH @baseId INCREMENT BY 1;

ALTER TABLE dbo.Posts
    ADD CONSTRAINT DF_Posts_Sequence DEFAULT NEXT VALUE FOR dbo.PostsIdSequence FOR "ID";

COMMIT TRANSACTION;

答案2

得分: 3

以下是一个示例,使用SWITCH将数据移动到具有相同模式且已具有IDENTITY的另一个表中。

--创建示例表和数据
CREATE TABLE dbo.AddIdentityExample(
  IncrementalColumn int NOT NULL
    CONSTRAINT PK_AddIdentityExample PRIMARY KEY
  , OtherData varchar(20) NULL
  );
CREATE INDEX idx_AddIdentityExample_OtherData
  ON dbo.AddIdentityExample(OtherData);
INSERT INTO dbo.AddIdentityExample VALUES
  (1, '样本数据一')
  , (2, '样本数据二')
  , (3, '样本数据三');
GO

SET XACT_ABORT ON;
BEGIN TRY
  BEGIN TRAN;
  --创建具有相同模式、索引和约束的临时表
  CREATE TABLE dbo.AddIdentityExampleStaging(
      IncrementalColumn int IDENTITY NOT NULL --添加IDENTITY列属性
        CONSTRAINT PK_AddIdentityExampleStaging PRIMARY KEY
    , OtherData varchar(20) NULL
    );
  CREATE INDEX idx_AddIdentityExampleStaging_OtherData
    ON dbo.AddIdentityExampleStaging(OtherData);

  --将数据从源表移动到新表
  ALTER TABLE dbo.AddIdentityExample
    SWITCH TO dbo.AddIdentityExampleStaging;
  DROP TABLE dbo.AddIdentityExample;
  --重命名表
  EXEC sp_rename
      @objname = N'dbo.AddIdentityExampleStaging'
    , @newname = N'AddIdentityExample'
    , @objtype = 'OBJECT';
  --重命名约束
  EXEC sp_rename
      @objname = N'dbo.PK_AddIdentityExampleStaging'
    , @newname = N'PK_AddIdentityExample'
    , @objtype = 'OBJECT';
  --重命名索引
  EXEC sp_rename
      @objname = N'dbo.AddIdentityExample.idx_AddIdentityExampleStaging_OtherData'
    , @newname = N'idx_AddIdentityExampleStaging_OtherData'
    , @objtype = N'INDEX';
  --使用当前最大列值设置IDENTITY种子
  DBCC CHECKIDENT(N'dbo.AddIdentityExample');
  COMMIT;
END TRY
BEGIN CATCH
  IF @@TRANCOUNT > 0 ROLLBACK;
  THROW;
END CATCH;
GO
英文:

Below is an example that uses SWITCH to move data into another table of identical schema that already has the IDENTITY.

--create sample table and data
CREATE TABLE dbo.AddIdentityExample(
	  IncrementalColumn int NOT NULL
		CONSTRAINT PK_AddIdentityExample PRIMARY KEY
	, OtherData varchar(20) NULL
	);
CREATE INDEX idx_AddIdentityExample_OtherData
	ON dbo.AddIdentityExample(OtherData);
INSERT INTO dbo.AddIdentityExample VALUES
	  (1, 'Sample data one')
	, (2, 'Sample data two')
	, (3, 'Sample data three');
GO

SET XACT_ABORT ON;
BEGIN TRY
	BEGIN TRAN;
	--create staging table with same schema, indexes, and constraints
	CREATE TABLE dbo.AddIdentityExampleStaging(
		  IncrementalColumn int IDENTITY NOT NULL --IDENTITY column property added
			CONSTRAINT PK_AddIdentityExampleStaging PRIMARY KEY
		, OtherData varchar(20) NULL
		);
	CREATE INDEX idx_AddIdentityExampleStaging_OtherData
		ON dbo.AddIdentityExampleStaging(OtherData);

	--move data from source table into new table
    ALTER TABLE dbo.AddIdentityExample
		SWITCH TO dbo.AddIdentityExampleStaging;
	DROP TABLE dbo.AddIdentityExample;
	--rename table
	EXEC sp_rename
		  @objname = N'dbo.AddIdentityExampleStaging'
		, @newname = N'AddIdentityExample'
		, @objtype = 'OBJECT';
	--rename constraints
	EXEC sp_rename
		  @objname = N'dbo.PK_AddIdentityExampleStaging'
		, @newname = N'PK_AddIdentityExample'
		, @objtype = 'OBJECT';
	--rename indexes
	EXEC sp_rename
		  @objname = N'dbo.AddIdentityExample.idx_AddIdentityExampleStaging_OtherData'
		, @newname = N'idx_AddIdentityExampleStaging_OtherData'
		, @objtype = N'INDEX';
	--seed IDENTITY with current max column value
	DBCC CHECKIDENT(N'dbo.AddIdentityExample');
	COMMIT;
END TRY
BEGIN CATCH
	IF @@TRANCOUNT > 0 ROLLBACK;
	THROW;
END CATCH;
GO

huangapple
  • 本文由 发表于 2023年6月22日 06:00:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76527426.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定