ChatGPT解决这个技术问题 Extra ChatGPT

"Prevent saving changes that require the table to be re-created" negative effects

Preamble

I was modifying a column in SQL Server 2008 today, changing the datatype from something like currency(18,0) to (19,2).

I got the error "The changes you have made require the following tables to be dropped and re-created" from SQL Server.

Before you scramble to answer, please read the following:

I already know there is the option in Tools ► Options ► Designer ► Table and Database Designers ► Uncheck the box "Prevent saving changes that require table re-creation." ...so do not answer with that!

Actual question

My actual question is for something else, as follows:

Are there any negative effects / possible drawbacks of doing this?

Does the table actually get dropped and recreated automatically when this box is unchecked?

If so, is the table copy a 100% exact replica of the source table?

And if you are with MS SQL Server 2014 -> Extras>Options>Designer From the top menu.

A
Antoine Meltzheim

Tools --> Options --> Designers node --> Uncheck " Prevent saving changes that require table recreation ".


Read the question - this is EXACTLY what the OP said to not bother with, because he already knows it.
The question (from its very first version, I checked the history) asked for an explanation of any drawbacks of unchecking this box. You haven't even made an attempt to address the question.
A
Aaron Bertrand

The table is only dropped and re-created in cases where that's the only way SQL Server's Management Studio has been programmed to know how to do it.

There are certainly cases where it will do that when it doesn't need to, but there will also be cases where edits you make in Management Studio will not drop and re-create because it doesn't have to.

The problem is that enumerating all of the cases and determining which side of the line they fall on will be quite tedious.

This is why I like to use ALTER TABLE in a query window, instead of visual designers that hide what they're doing (and quite frankly have bugs) - I know exactly what is going to happen, and I can prepare for cases where the only possibility is to drop and re-create the table (which is some number less than how often SSMS will do that to you).

Are there any negative effects / possible drawbacks of doing this?

Sure. If you can script the change yourself without rebuilding the whole table, that's better - consider the case where the table is 10TB, and the database is heavily logged (think sync AG, change tracking, replication, poorly-written triggers), and the table is highly accessed - that's a potential recipe for disaster. If your change is something where you can apply an ONLINE hint or add a column and copy the data over in batches instead of all-or-nothing the GUI will do, this is better.

Does the table actually get dropped and recreated automatically when this box is unchecked?

It might. There is a laundry list of scenarios and the outcome is dependent on the version of SSMS, the version of SQL Server, and sometimes the edition. You can check by checking the box and trying to apply the change on a meaningless copy of the database first, but using actual ALTER TABLE scripts instead of the pointy-clicky GUI is the way to go IMHO.

If so, is the table copy a 100% exact replica of the source table?

Yes, if SSMS has to rebuild the table, it will be a 100% exact replica after it's done (except for the change of course), but that could be next Wednesday. The process creates a new version of the table, copies all the data to it, then drop the old table and renames the new one.


While a really good answer, I feel it doesn't provide answers to all of the questions raised by the OP, and those questions are the ones I'm interested in, actually. In particular Are there any negative effects / possible drawbacks of doing this? and If so, is the table copy a 100% exact replica of the source table?. Do you have any information regarding those questions?
@tfrascaroli Are there drawbacks to letting SSMS rebuild the table for you? Sure. If you can script the change yourself without rebuilding the whole table, that's better - consider the case where the table is 10TB, and the database is heavily logged (think sync AG, change tracking, replication), and the table is highly accessed - that's a potential recipe for disaster. The table will be a 100% exact replica after it's done, but that could be next Wednesday.
佚名

Reference - Turning off this option can help you avoid re-creating a table, it can also lead to changes being lost. For example, suppose that you enable the Change Tracking feature in SQL Server 2008 to track changes to the table. When you perform an operation that causes the table to be re-created, you receive the error message that is mentioned in the "Symptoms" section. However, if you turn off this option, the existing change tracking information is deleted when the table is re-created. Therefore,Microsoft recommend that you do not work around this problem by turning off the option.


C
Carol Baker West

SQL Server drops and recreates the tables only if you:

Add a new column

Change the Allow Nulls setting for a column

Change the column order in the table

Change the column data type

Using ALTER is safer, as in case the metadata is lost while you re-create the table, your data will be lost.


Your list is not exhaustive. Add/remove the IDENTITY property on a column, for example.
Adding a new column to the end of the fields that is NULLABLE does not require a table rebuild.
A
Andrew Hill

Yes, there are negative effects from this:

If you script out a change blocked by this flag you get something like the script below (all i am turning the ID column in Contact into an autonumbered IDENTITY column, but the table has dependencies). Note potential errors that can occur while the following is running:

Even microsoft warns that this may cause data loss (that comment is auto-generated)! for a period of time, foreign keys are not enforced. if you manually run this in ssms and the ' EXEC('INSERT INTO ' fails, and you let the following statements run (which they do by default, as they are split by 'go') then you will insert 0 rows, then drop the old table. if this is a big table, the runtime of the insert can be large, and the transaction is holding a schema modification lock, so blocks many things.

--

/* 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