从表中的列中删除标识

Con*_*ger 111 sql t-sql sql-server

我们有一个5GB的表(接近5亿行),我们想删除其中一个列上的标识属性,但是当我们尝试通过SSMS执行此操作时 - 它会超时.

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

Ada*_*ger 126

IDENTITY一旦设置,您就无法删除规范.

要删除整个列:

ALTER TABLE yourTable
DROP COLUMN yourCOlumn;
Run Code Online (Sandbox Code Playgroud)

有关ALTER TABLE的信息

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

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

  • @simon如果你编写了你的​​更改脚本,你会看到SSMS实际上是创建了一个没有identity属性的表的副本. (32认同)
  • 您可以删除标识规范.实际上我昨天必须使用SSMS,尽管不是5亿行. (3认同)
  • 我只想添加将新列重命名为原始列的名称.此外,如果这个`identity`列被用作另一个表中的`foreign key`的一部分,那么你将不得不首先删除约束,然后采取行动,如@AdamWenger所提到的关于删除身份`属性/属性..您还可以查看此链接,了解有关仅删除属性的更多详细信息:http://blog.sqlauthority.com/2009/05/03/sql-server-add-or-remove-identity-property-on-专栏/ ..好运! (3认同)
  • 对于投反对票的人 - 我很高兴听到您对我的回答不满意的地方。 (2认同)
  • 看看下面 Mark Sowul 的回答。无需在列之间移动数据。使用马克的答案,你只是在打乱元数据。除非您正在处理具有数千万或数亿行的表,否则没什么大不了的。加号的答案阻止了表模式中列的重新定位。我刚刚尝试了一下,效果非常好。非常聪明。 (2认同)

Mar*_*wul 81

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

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

例如,给定:

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';
Run Code Online (Sandbox Code Playgroud)

您可以执行以下操作:

--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 
IF NOT EXISTS (SELECT * FROM Original) 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;
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案.这是在没有大量数据迁移的情况下删除标识列的唯一真正方法. (8认同)
  • 如果使用SQL Management Studio编写表格脚本,请务必打开工具>选项> SQL Server对象资源管理器>脚本>表格并查看选项>脚本索引(默认为False) (3认同)

Bri*_*y37 58

这会受到外键和主键约束的影响,所以这里有一些脚本可以帮助你:

首先,创建一个具有临时名称的重复列:

alter table yourTable add tempId int NOT NULL default -1;
update yourTable set tempId = id;
Run Code Online (Sandbox Code Playgroud)

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

SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'yourTable';
Run Code Online (Sandbox Code Playgroud)

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

ALTER TABLE yourTable DROP CONSTRAINT PK_yourTable_id;
Run Code Online (Sandbox Code Playgroud)

如果你有外键,它将失败,所以如果这样,删除外键约束. 保持记录,你可以运行这个,因为你可以在以后加入限制!

SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'otherTable';
alter table otherTable drop constraint fk_otherTable_yourTable;
commit;
..
Run Code Online (Sandbox Code Playgroud)

删除所有外键约束后,您将能够删除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;
Run Code Online (Sandbox Code Playgroud)

最后,添加FK约束:

alter table otherTable add constraint fk_otherTable_yourTable foreign key (yourTable_id) references yourTable(id);
..
Run Code Online (Sandbox Code Playgroud)

El Fin!


小智 17

我刚遇到同样的问题.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';

  • 如果您对旧列有任何限制,事情就不是这么简单了。 (5认同)

blu*_*dot 10

以下脚本删除名为"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
Run Code Online (Sandbox Code Playgroud)


Zol*_*ari 5

当我们不知道标识列名称时,波纹管代码可以正常工作。

需要将数据复制到新的临时表中,例如Invoice_DELETED. 下次我们使用:

insert into Invoice_DELETED select * from Invoice where ...


SELECT t1.*
INTO Invoice_DELETED
FROM Invoice t1
LEFT JOIN Invoice ON 1 = 0
--WHERE t1.InvoiceID = @InvoiceID
Run Code Online (Sandbox Code Playgroud)

更多解释请参见:https : //dba.stackexchange.com/a/138345/101038


小智 5

在 SQL Server 中,您可以像这样打开和关闭身份插入:

SET IDENTITY_INSERT 表名 ON

-- 在这里运行您的查询

SET IDENTITY_INSERT 表名 OFF