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

前端 未结 5 844
抹茶落季
抹茶落季 2020-12-04 06:00

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

相关标签:
5条回答
  • 2020-12-04 06:42

    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).

    0 讨论(0)
  • 2020-12-04 06:44

    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.

    0 讨论(0)
  • 2020-12-04 06:48

    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.

    0 讨论(0)
  • 2020-12-04 06:51

    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:

    1. Even microsoft warns that this may cause data loss (that comment is auto-generated)!
    2. for a period of time, foreign keys are not enforced.
    3. 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.
    4. 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
    
    0 讨论(0)
  • 2020-12-04 06:52

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

    0 讨论(0)
提交回复
热议问题