Efeitos negativos "Evitar salvar alterações que exigem a recriação da tabela"

255

Preâmbulo

Hoje eu estava modificando uma coluna no SQL Server 2008, alterando o tipo de dados de algo como moeda (18,0) para (19,2).

Eu recebi o erro "As alterações feitas exigem que as tabelas a seguir sejam eliminadas e recriadas" no SQL Server.

Antes de tentar responder, leia o seguinte:

Já sei que existe a opção em Ferramentas ► Opções ► Designer ► Designers de tabela e banco de dados ► Desmarque a caixa "Impedir salvar alterações que exijam a recriação da tabela". Impedir salvar alterações que exigem recriação de tabela em cinco cliques ... então não responda com isso!

Pergunta real

Minha pergunta real é para outra coisa, como segue:

Existem efeitos negativos / possíveis inconvenientes em fazer isso?

A tabela é realmente descartada e recriada automaticamente quando esta caixa está desmarcada?

Em caso afirmativo, a tabela copia uma réplica exata 100% da tabela de origem?

CF_HoneyBadger
fonte
65
Ferramentas> Opções> Designer ... era isso que eu estava procurando! Obrigado!
Nrod 3/04
1
também dar uma olhada em stackoverflow.com/questions/9870968/...
pylover
2
E se você estiver com o MS SQL Server 2014 -> Extras> Opções> Designer No menu superior.
Vityata 7/07

Respostas:

89

A tabela é descartada e recriada apenas nos casos em que essa é a única maneira de programar o Management Studio do SQL Server para saber como fazê-lo.

Certamente, há casos em que isso é feito quando não é necessário, mas também há casos em que as edições feitas no Management Studio não são eliminadas e recriadas porque não é necessário.

O problema é que enumerar todos os casos e determinar em que lado da linha eles se encaixam será bastante tedioso.

É por isso que gosto de usar ALTER TABLEem uma janela de consulta, em vez de designers visuais que ocultam o que estão fazendo (e francamente têm bugs) - sei exatamente o que vai acontecer e posso me preparar para casos em que a única possibilidade é soltar e recriar a tabela (que é um número menor que a frequência com que o SSMS fará isso com você).

Aaron Bertrand
fonte
5
Embora seja uma resposta muito boa, acho que ela não fornece respostas para todas as perguntas levantadas pelo OP, e essas são as que me interessam, na verdade. Em particular, existem efeitos negativos / possíveis inconvenientes em fazer isso? e Se sim, a cópia da tabela é uma réplica 100% exata da tabela de origem? . Você tem alguma informação sobre essas perguntas?
tfrascaroli
252

Ferramentas -> Opções -> Nó Designers -> Desmarque a opção " Impedir salvar alterações que exigem recreação na tabela ".

Antoine Meltzheim
fonte
12

Referência - desativar essa opção pode ajudar a evitar a recriação de uma tabela, mas também pode levar à perda de alterações. Por exemplo, suponha que você habilite o recurso Rastreamento de Alterações no SQL Server 2008 para rastrear alterações na tabela. Quando você executa uma operação que faz com que a tabela seja recriada, você recebe a mensagem de erro mencionada na seção "Sintomas". No entanto, se você desativar essa opção, as informações de rastreamento de alterações existentes serão excluídas quando a tabela for recriada. Portanto, a Microsoft recomenda que você não solucione esse problema desativando a opção.


fonte
11

O SQL Server descarta e recria as tabelas somente se você:

  • Adicione uma nova coluna
  • Alterar a configuração Permitir nulos para uma coluna
  • Alterar a ordem das colunas na tabela
  • Alterar o tipo de dados da coluna

O uso de ALTER é mais seguro, pois caso os metadados sejam perdidos enquanto você recria a tabela, seus dados serão perdidos.

Carol Baker West
fonte
8
Sua lista não é completa. Adicione / remova a IDENTITYpropriedade em uma coluna, por exemplo.
Aaron Bertrand
2
Adicionar uma nova coluna ao final dos campos NULLABLE não requer uma reconstrução da tabela.
PseudoToad
2

Sim, existem efeitos negativos disso:

Se você escreve uma alteração bloqueada por esse sinalizador, obtém algo como o script abaixo (tudo o que estou transformando da coluna ID em Contato é uma coluna IDENTITY com numeração automática, mas a tabela possui dependências). Observe possíveis erros que podem ocorrer enquanto o seguinte estiver em execução:

  1. Até a Microsoft avisa que isso pode causar perda de dados (esse comentário é gerado automaticamente)!
  2. por um período de tempo, as chaves estrangeiras não são aplicadas.
  3. se você executar manualmente isso nos ssms e o 'EXEC (' INSERT INTO 'falhar, e você permitir que as seguintes instruções sejam executadas (que são executadas por padrão, pois são divididas por' ir ')), você inserirá 0 linhas e soltará a mesa velha.
  4. se essa é uma tabela grande, o tempo de execução da inserção pode ser grande e a transação está mantendo um bloqueio de modificação de esquema, bloqueando muitas coisas.

-

/* 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
Andrew Hill
fonte