«Запретить сохранение изменений, которые требуют пересоздания таблицы» негативные эффекты

255

преамбула

Сегодня я изменял столбец в SQL Server 2008, меняя тип данных с чего-то вроде валюты (18,0) на (19,2).

Я получил сообщение об ошибке «Внесенные вами изменения требуют удаления и повторного создания следующих таблиц» с SQL Server.

Прежде чем ответить, пожалуйста, прочитайте следующее:

Я уже знаю, что есть опция в Инструменты ► Параметры ► Дизайнер ► Дизайнеры таблиц и баз данных ► Снимите флажок «Запретить сохранение изменений, которые требуют пересоздания таблицы». Запретить сохранение изменений, которые требуют воссоздания таблицы в пять кликов ... так что не отвечай с этим!

Актуальный вопрос

Мой актуальный вопрос для чего-то другого, а именно:

Есть ли какие-либо негативные последствия / возможные недостатки этого?

Действительно ли таблица удаляется и воссоздается автоматически, если этот флажок снят?

Если да, является ли таблица точной копией 100% точной копии исходной таблицы?

CF_HoneyBadger
источник
65
Инструменты> Параметры> Дизайнер ... это было то, что я искал! Спасибо!
nrod
1
Также обратите внимание на stackoverflow.com/questions/9870968/...
pylover
2
А если вы используете MS SQL Server 2014 -> Дополнения> Параметры> Дизайнер Из верхнего меню.
Витя

Ответы:

89

Таблица удаляется и воссоздается только в тех случаях, когда это единственный способ, которым SQL Server Management Studio был запрограммирован, чтобы знать, как это сделать.

Конечно, есть случаи, когда он будет делать это, когда в этом нет необходимости, но также будут случаи, когда изменения, которые вы вносите в Management Studio, не будут сбрасываться и пересоздаваться, потому что это не нужно.

Проблема в том, что перечислять все случаи и определять, на какую сторону линии они попадают, будет довольно утомительно.

Вот почему мне нравится использовать ALTER TABLEв окне запросов вместо визуальных дизайнеров, которые скрывают то, что они делают (и, откровенно говоря, есть ошибки) - я точно знаю, что произойдет, и я могу подготовиться к случаям, когда единственная возможность это удалить и заново создать таблицу (что на некоторое число меньше, чем то, как часто SSMS будет делать это с вами).

Аарон Бертран
источник
5
Хотя это действительно хороший ответ, я чувствую, что он не дает ответов на все вопросы, поднятые ОП, и на самом деле эти вопросы меня интересуют. В частности Есть ли какие-либо негативные последствия / возможные недостатки в этом? и если да, то является ли копия таблицы 100% точной копией исходной таблицы? , У вас есть информация по этим вопросам?
tfrascaroli
252

Сервис -> Параметры -> Узел Дизайнеры -> Снимите флажок « Запретить сохранение изменений, требующих воссоздания таблицы ».

Антуан Мельцхайм
источник
12

Справка. Отключение этой опции поможет избежать повторного создания таблицы, а также может привести к потере изменений. Например, предположим, что вы включили функцию отслеживания изменений в SQL Server 2008, чтобы отслеживать изменения в таблице. Когда вы выполняете операцию, которая вызывает повторное создание таблицы, вы получаете сообщение об ошибке, упомянутое в разделе «Проблема». Однако если вы отключите эту опцию, существующая информация об отслеживании изменений будет удалена при повторном создании таблицы. Поэтому Microsoft рекомендует не обходить эту проблему, отключив этот параметр.


источник
11

SQL Server удаляет и воссоздает таблицы, только если вы:

  • Добавить новый столбец
  • Изменить параметр «Разрешить пустые значения» для столбца
  • Изменить порядок столбцов в таблице
  • Изменить тип данных столбца

Использование ALTER более безопасно, так как в случае потери метаданных при повторном создании таблицы ваши данные будут потеряны.

Кэрол Бейкер Вест
источник
8
Ваш список не является исчерпывающим. IDENTITYНапример, добавьте / удалите свойство столбца.
Аарон Бертран
2
Добавление нового столбца в конец полей, который имеет значение NULLABLE, не требует перестроения таблицы.
PseudoToad
2

Да, есть негативные последствия от этого:

Если вы запишите сценарий изменения, заблокированного этим флагом, вы получите что-то вроде приведенного ниже сценария (все, что я превращаю столбец идентификатора в Контакте в столбец с автоматическим номером IDENTITY, но у таблицы есть зависимости). Обратите внимание на возможные ошибки, которые могут возникнуть при выполнении следующих действий:

  1. Даже Microsoft предупреждает, что это может привести к потере данных (этот комментарий генерируется автоматически)!
  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
Эндрю Хилл
источник