“防止保存需要重新创build表的更改”的负面影响
前言
我今天正在修改SQL Server 2008中的列,将数据types从货币(18,0)更改为(19,2)。
我从SQL Server得到错误“您所做的更改需要删除和重新创build下列表”。
在您抢答之前,请阅读以下内容:
我已经知道在工具►选项►devise器►表格和数据库devise器中有选项►取消选中 “保存需要重新创build表格的更改” checkbox 。 …所以不要回答这个!
实际的问题
我的实际问题是其他的东西,如下所示:
这样做是否有任何负面影响/可能的弊端?
当这个框被取消选中时,表是否实际上被丢弃和重新创build?
如果是这样,表是否复制了源表的100%完全相同的副本?
只有SQL Server的Management Studio已经被编程来知道如何去做的时候,表格才会被删除和重新创build。
在某些情况下,如果不需要这样做,也会出现这样的情况:您在Management Studio中所做的编辑不会因为不必删除而重新创build。
问题是,列举所有的情况,并确定他们的哪一边将是相当繁琐的。
这就是为什么我喜欢在查询窗口中使用ALTER TABLE
,而不是隐藏他们正在做什么的可视化devise者(而且坦率地说有bug) – 我确切地知道将会发生什么,并且我可以准备唯一的可能性是删除并重新创build表(这是一个数字less于SSMS多久会这样做给你)。
工具 – >选项 – >devise师节点 – >取消选中“阻止保存需要表格重新创build的更改”。
参考 – closures此选项可以帮助您避免重新创build表格,还可能导致更改丢失。 例如,假设您启用SQL Server 2008中的更改跟踪function来跟踪对表的更改。 当您执行重新创build表的操作时,您会收到“症状”部分中提到的错误消息。 但是,如果closures此选项,则在重新创build表时将删除现有的更改跟踪信息。 因此,Microsoftbuild议您不要通过closures该选项来解决此问题。
只有在以下情况下,SQL Server才会删除并重新创build表:
- 添加一个新的列
- 更改列的允许空值设置
- 更改表格中的列顺序
- 更改列数据types
使用ALTER更安全,因为在您重新创build表时元数据丢失的情况下,您的数据将会丢失。
是的,这有负面影响:
如果你脚本化了一个被这个标志阻塞的变化,你可以得到类似下面的脚本(我把Contact中的ID列变成自动编号的IDENTITY列,但是表格有依赖关系)。 请注意以下情况下可能发生的潜在错误:
- 即使微软警告,这可能会导致数据丢失(该评论是自动生成的)!
- 一段时间内,外键不被强制执行。
- 如果你在ssms中手动运行这个函数,并且'EXEC('INSERT INTO'失败,并且让下面的语句运行(默认情况下它们是由'go'分隔的),那么你将插入0行,然后drop旧桌子。
- 如果这是一个大表,插入的运行时可能很大,并且事务持有一个模式修改锁,所以阻塞了很多事情。
–
/* To prevent any potential data loss issues, you should review this script in detail before running it outside the context of the database designer.*/ BEGIN TRANSACTION GO ALTER TABLE raw.Contact DROP CONSTRAINT fk_Contact_AddressType GO ALTER TABLE ref.ContactpointType SET (LOCK_ESCALATION = TABLE) GO COMMIT BEGIN TRANSACTION GO ALTER TABLE raw.Contact DROP CONSTRAINT fk_contact_profile GO ALTER TABLE raw.Profile SET (LOCK_ESCALATION = TABLE) GO COMMIT BEGIN TRANSACTION GO CREATE TABLE raw.Tmp_Contact ( ContactID int NOT NULL IDENTITY (1, 1), ProfileID int NOT NULL, AddressType char(2) NOT NULL, ContactText varchar(250) NULL ) ON [PRIMARY] GO ALTER TABLE raw.Tmp_Contact SET (LOCK_ESCALATION = TABLE) GO SET IDENTITY_INSERT raw.Tmp_Contact ON GO IF EXISTS(SELECT * FROM raw.Contact) EXEC('INSERT INTO raw.Tmp_Contact (ContactID, ProfileID, AddressType, ContactText) SELECT ContactID, ProfileID, AddressType, ContactText FROM raw.Contact WITH (HOLDLOCK TABLOCKX)') GO SET IDENTITY_INSERT raw.Tmp_Contact OFF GO ALTER TABLE raw.PostalAddress DROP CONSTRAINT fk_AddressProfile GO ALTER TABLE raw.MarketingFlag DROP CONSTRAINT fk_marketingflag_contact GO ALTER TABLE raw.Phones DROP CONSTRAINT fk_phones_contact GO DROP TABLE raw.Contact GO EXECUTE sp_rename N'raw.Tmp_Contact', N'Contact', 'OBJECT' GO ALTER TABLE raw.Contact ADD CONSTRAINT Idx_Contact_1 PRIMARY KEY CLUSTERED ( ProfileID, ContactID ) GO ALTER TABLE raw.Contact ADD CONSTRAINT Idx_Contact UNIQUE NONCLUSTERED ( ProfileID, ContactID ) GO CREATE NONCLUSTERED INDEX idx_Contact_0 ON raw.Contact ( AddressType ) GO ALTER TABLE raw.Contact ADD CONSTRAINT fk_contact_profile FOREIGN KEY ( ProfileID ) REFERENCES raw.Profile ( ProfileID ) ON UPDATE NO ACTION ON DELETE NO ACTION GO ALTER TABLE raw.Contact ADD CONSTRAINT fk_Contact_AddressType FOREIGN KEY ( AddressType ) REFERENCES ref.ContactpointType ( ContactPointTypeCode ) ON UPDATE NO ACTION ON DELETE NO ACTION GO COMMIT BEGIN TRANSACTION GO ALTER TABLE raw.Phones ADD CONSTRAINT fk_phones_contact FOREIGN KEY ( ProfileID, PhoneID ) REFERENCES raw.Contact ( ProfileID, ContactID ) ON UPDATE NO ACTION ON DELETE NO ACTION GO ALTER TABLE raw.Phones SET (LOCK_ESCALATION = TABLE) GO COMMIT BEGIN TRANSACTION GO ALTER TABLE raw.MarketingFlag ADD CONSTRAINT fk_marketingflag_contact FOREIGN KEY ( ProfileID, ContactID ) REFERENCES raw.Contact ( ProfileID, ContactID ) ON UPDATE NO ACTION ON DELETE NO ACTION GO ALTER TABLE raw.MarketingFlag SET (LOCK_ESCALATION = TABLE) GO COMMIT BEGIN TRANSACTION GO ALTER TABLE raw.PostalAddress ADD CONSTRAINT fk_AddressProfile FOREIGN KEY ( ProfileID, AddressID ) REFERENCES raw.Contact ( ProfileID, ContactID ) ON UPDATE NO ACTION ON DELETE NO ACTION GO ALTER TABLE raw.PostalAddress SET (LOCK_ESCALATION = TABLE) GO COMMIT