从表中删除标识

我们有一个5GB的表(接近5亿行),我们要删除其中一列的标识属性,但是当我们试图通过SSMS来实现时,它会超时。

这可以通过T-SQL完成吗?

一旦设置,您就不能删除一个IDENTITY规范。

要删除整个列:

 ALTER TABLE yourTable DROP COLUMN yourCOlumn; 

有关ALTER TABLE的信息

如果您需要保留数据,但删除IDENTITY列,则需要:

  • 创build一个新的列
  • 将数据从现有的IDENTITY列传输到新列
  • 删除现有的IDENTITY列。
  • 将新列重命名为原始列名称

这与外键和主键约束混乱,所以这里有一些脚本可以帮助你:

首先,创build一个临时名称的重复列:

 alter table yourTable add tempId int NOT NULL default -1; update yourTable set tempId = id; 

接下来,获取您的主键约束的名称:

 SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'yourTable'; 

现在尝试删除列的主键约束:

 ALTER TABLE yourTable DROP CONSTRAINT PK_yourTable_id; 

如果你有外键,它将会失败,所以如果这样的话放弃外键约束。 保持你所跑的这张桌子的轨迹,因此你可以在以后添加这些限制!

 SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'otherTable'; alter table otherTable drop constraint fk_otherTable_yourTable; commit; .. 

一旦你所有的外键约束都被删除,你将能够删除PK约束,删除该列,重命名你的临时列,并将PK约束添加到该列:

 ALTER TABLE yourTable DROP CONSTRAINT PK_yourTable_id; alter table yourTable drop column id; EXEC sp_rename 'yourTable.tempId', 'id', 'COLUMN'; ALTER TABLE yourTable ADD CONSTRAINT PK_yourTable_id PRIMARY KEY (id) commit; 

最后,将FK限制添加回来:

 alter table otherTable add constraint fk_otherTable_yourTable foreign key (yourTable_id) references yourTable(id); .. 

El Fin!

如果你想在不添加和填充新列的 情况下执行此操作, 而不对列进行重新sorting ,并且几乎没有停机时间,因为表上没有数据发生变化,所以让我们借助分区function做一些魔术(但由于没有使用分区,需要企业版):

  1. 删除指向此表的所有外键
  2. 编写要创build的表的脚本; 重命名所有例如'MyTable2','MyIndex2'等。删除IDENTITY规范。
  3. 您现在应该有两个“完全相同”的表格,一个是完整的,另一个是空的,没有IDENTITY。
  4. 运行ALTER TABLE [Original] SWITCH TO [Original2]
  5. 现在你的原始表将是空的,新的将有数据。 您已经切换了两个表的元数据(即时)。
  6. 删除原来的(现在是空的表), exec sys.sp_rename以将各种模式对象重命名为原始名称,然后重新创build外键。

例如,给出:

 CREATE TABLE Original ( Id INT IDENTITY PRIMARY KEY , Value NVARCHAR(300) ); CREATE NONCLUSTERED INDEX IX_Original_Value ON Original (Value); INSERT INTO Original SELECT 'abcd' UNION ALL SELECT 'defg'; 

您可以执行以下操作:

 --create new table with no IDENTITY CREATE TABLE Original2 ( Id INT PRIMARY KEY , Value NVARCHAR(300) ); CREATE NONCLUSTERED INDEX IX_Original_Value2 ON Original2 (Value); --data before switch SELECT 'Original', * FROM Original UNION ALL SELECT 'Original2', * FROM Original2; ALTER TABLE Original SWITCH TO Original2; --data after switch SELECT 'Original', * FROM Original UNION ALL SELECT 'Original2', * FROM Original2; --clean up DROP TABLE Original; EXEC sys.sp_rename 'Original2.IX_Original_Value2', 'IX_Original_Value', 'INDEX'; EXEC sys.sp_rename 'Original2', 'Original', 'OBJECT'; UPDATE Original SET Id = Id + 1; SELECT * FROM Original; 

我只是有同样的问题。 SSMS中的4条语句,而不是使用GUI,速度非常快。

  • 做一个新的专栏

    alter table users add newusernum int;

  • 复制值

    update users set newusernum=usernum;

  • 放下旧的专栏

    alter table users drop column usernum;

  • 将新列重命名为旧列名称

    EXEC sp_RENAME 'users.newusernum' , 'usernum', 'COLUMN';

以下脚本删除名为“Id”的列的标识字段

希望它有帮助。

 BEGIN TRAN BEGIN TRY EXEC sp_rename '[SomeTable].[Id]', 'OldId'; ALTER TABLE [SomeTable] ADD Id int NULL EXEC ('UPDATE [SomeTable] SET Id = OldId') ALTER TABLE [SomeTable] NOCHECK CONSTRAINT ALL ALTER TABLE [SomeTable] DROP CONSTRAINT [PK_constraintName]; ALTER TABLE [SomeTable] DROP COLUMN OldId ALTER TABLE [SomeTable] ALTER COLUMN [Id] INTEGER NOT NULL ALTER TABLE [SomeTable] ADD CONSTRAINT PK_JobInfo PRIMARY KEY (Id) ALTER TABLE [SomeTable] CHECK CONSTRAINT ALL COMMIT TRAN END TRY BEGIN CATCH ROLLBACK TRAN SELECT ERROR_MESSAGE () END CATCH 

贝娄的代码工作的很好, 当我们不知道身份列名

并且想要将数据复制到像Invoice_DELETED这样的新临时表中。 下一次我们使用:插入Invoice_DELETED select *从发票其中…

 SELECT t1.* INTO Invoice_DELETED FROM Invoice t1 LEFT JOIN Invoice ON 1 = 0 --WHERE t1.InvoiceID = @InvoiceID 

特别感谢'Andriy M'

有关更多解释,请参阅: https : //dba.stackexchange.com/a/138345/101038