从表中删除标识
我们有一个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做一些魔术(但由于没有使用分区,需要企业版):
- 删除指向此表的所有外键
- 编写要创build的表的脚本; 重命名所有例如'MyTable2','MyIndex2'等。删除IDENTITY规范。
- 您现在应该有两个“完全相同”的表格,一个是完整的,另一个是空的,没有IDENTITY。
- 运行
ALTER TABLE [Original] SWITCH TO [Original2]
- 现在你的原始表将是空的,新的将有数据。 您已经切换了两个表的元数据(即时)。
- 删除原来的(现在是空的表),
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