“防止保存需要重新创建表的更改”的负面影响


255

前言

我今天修改了SQL Server 2008中的一列,将数据类型从currency(18,0)更改为(19,2)。

我从SQL Server中收到错误消息“所做的更改要求删除并重新创建下表”。

在争夺答案之前,请阅读以下内容:

我已经知道在“ 工具”►“选项”►“设计器”►“表和数据库设计器”►取消选中 “防止保存需要重新创建表的更改” 框,这是一个选项。 防止保存需要五次单击即可重新创建表的更改 ...所以不要回答!

实际问题

我的实际问题是其他问题,如下所示:

这样做有没有负面影响/可能的弊端?

取消选中此框后,实际上是否会自动删除并重新创建表?

如果是这样,该表副本是否是源表的100%精确副本?


65
工具>选项>设计器...这就是我一直在寻找的!谢谢!
nrod


2
如果您使用的是MS SQL Server 2014->附加功能>选项>设计器,请从顶部菜单中选择。
Vityata '16

Answers:


89

仅当SQL Server的Management Studio已被编程为知道如何执行此操作的唯一方法时,才删除并重新创建该表。

当然,在某些情况下不需要时会执行此操作,但是在某些情况下,您在Management Studio中所做的编辑不会因为不需要而放弃并重新创建。

问题在于,列举所有情况并确定它们落在生产线的哪一边会非常繁琐。

这就是为什么我喜欢ALTER TABLE在查询窗口中使用,而不是用视觉设计器隐藏他们正在做的事情(坦率地说,有错误)的原因-我确切地知道会发生什么,并且我可以为唯一可能的情况做准备就是删除并重新创建表(该数目比SSMS对您执行此操作的频率要少一些)。


5
虽然这是一个很好的答案,但我认为它不能为OP提出的所有问题提供答案,而这些问题实际上是我感兴趣的问题。特别是这样做是否有负面影响/可能有弊端?如果是这样,则表复制源表的100%的精确复制品?。您是否有关于这些问题的信息?
tfrascaroli


12

参考 -禁用此选项可以帮助您避免重新创建表,也可能导致更改丢失。例如,假设您启用了SQL Server 2008中的“更改跟踪”功能以跟踪对表的更改。当您执行导致重新创建该表的操作时,您收到“症状”一节中提到的错误消息。但是,如果关闭此选项,则在重新创建表时将删除现有的更改跟踪信息。因此,Microsoft建议您不要通过关闭该选项来解决此问题。


11

只有在以下情况下,SQL Server才会删除并重新创建表:

  • 添加新列
  • 更改列的允许空值设置
  • 更改表格中的列顺序
  • 更改列数据类型

使用ALTER更安全,因为如果在重新创建表时元数据丢失,则数据将丢失。


8
您的清单并不详尽。IDENTITY例如,在列上添加/删除属性。
亚伦·伯特兰

2
将新列添加到字段NULLABLE的末尾不需要重新构建表。
PseudoToad 2014年

2

是的,这有负面影响:

如果您编写出此标志阻止的更改的脚本,则会得到类似以下脚本的内容(所有我都将Contact中的ID列转换为自动编号的IDENTITY列,但该表具有依赖性)。请注意在运行以下程序时可能发生的潜在错误:

  1. 甚至微软警告说,这可能会导致数据丢失(该注释是自动生成的)!
  2. 在一段时间内,不强制使用外键。
  3. 如果您在ssms中手动运行此命令,并且'EXEC('INSERT INTO'失败,并且让以下语句运行(它们默认执行,因为它们被'go'分隔),则将插入0行,然后删除旧桌子。
  4. 如果这是一个大表,则插入的运行时可能会很大,并且事务持有模式修改锁,因此会阻塞许多事情。

--

/* 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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.