Efectos negativos "Evitar guardar cambios que requieren que la tabla se vuelva a crear"

255

Preámbulo

Hoy estaba modificando una columna en SQL Server 2008, cambiando el tipo de datos de algo como moneda (18,0) a (19,2).

Recibí el error "Los cambios que ha realizado requieren que se eliminen y se vuelvan a crear las siguientes tablas" de SQL Server.

Antes de luchar para responder, lea lo siguiente:

Ya sé que existe la opción en Herramientas ► Opciones ► Diseñador ► Diseñadores de tablas y bases de datos ► Desmarque la casilla "Evitar guardar cambios que requieren la recreación de la tabla". Evite guardar cambios que requieren la recreación de la tabla en cinco clics ... así que no respondas con eso!

Pregunta real

Mi pregunta real es para otra cosa, como sigue:

¿Hay algún efecto negativo / posibles inconvenientes de hacer esto?

¿La tabla se cae y se recrea automáticamente cuando esta casilla no está marcada?

Si es así, ¿la tabla copia una réplica 100% exacta de la tabla fuente?

CF_HoneyBadger
fuente
65
Herramientas> Opciones> Diseñador ... ¡eso era lo que estaba buscando! ¡Gracias!
nrod
1
también eche un vistazo a stackoverflow.com/questions/9870968/…
pylover
2
Y si está con MS SQL Server 2014 -> Extras> Opciones> Diseñador Desde el menú superior.
Vityata

Respuestas:

89

La tabla solo se descarta y se vuelve a crear en los casos en que esa es la única forma en que se ha programado Management Studio de SQL Server para saber cómo hacerlo.

Ciertamente, habrá casos en los que lo hará cuando no sea necesario, pero también habrá casos en que las ediciones que realice en Management Studio no se eliminen y se vuelvan a crear porque no es necesario.

El problema es que enumerar todos los casos y determinar en qué lado de la línea caen será bastante tedioso.

Es por eso que me gusta usar ALTER TABLEen una ventana de consulta, en lugar de diseñadores visuales que ocultan lo que están haciendo (y francamente tienen errores): sé exactamente lo que sucederá y puedo prepararme para los casos en que la única posibilidad es soltar y volver a crear la tabla (que es un número menor que la frecuencia con la que SSMS te hará eso).

Aaron Bertrand
fuente
55
Si bien es una respuesta realmente buena, creo que no proporciona respuestas a todas las preguntas planteadas por el OP, y esas preguntas son las que realmente me interesan. En particular ¿Hay algún efecto negativo / posibles inconvenientes de hacer esto? y si es así, ¿la tabla copia una réplica 100% exacta de la tabla fuente? . ¿Tienes alguna información sobre esas preguntas?
tfrascaroli
252

Herramientas -> Opciones -> Nodo de diseñadores -> Desmarque " Evitar guardar cambios que requieren recreación de tabla ".

Antoine Meltzheim
fuente
12

Referencia : desactivar esta opción puede ayudarlo a evitar volver a crear una tabla, también puede provocar la pérdida de cambios. Por ejemplo, suponga que habilita la función de seguimiento de cambios en SQL Server 2008 para realizar un seguimiento de los cambios en la tabla. Cuando realiza una operación que hace que la tabla se vuelva a crear, recibirá el mensaje de error que se menciona en la sección "Síntomas". Sin embargo, si desactiva esta opción, la información de seguimiento de cambios existente se elimina cuando se vuelve a crear la tabla. Por lo tanto, Microsoft recomienda que no solucione este problema desactivando la opción.


fuente
11

SQL Server descarta y recrea las tablas solo si usted:

  • Agregar una nueva columna
  • Cambiar la configuración Permitir nulos para una columna
  • Cambiar el orden de las columnas en la tabla
  • Cambiar el tipo de datos de la columna

Usar ALTER es más seguro, ya que en caso de que los metadatos se pierdan mientras vuelve a crear la tabla, sus datos se perderán.

Carol Baker West
fuente
8
Tu lista no es exhaustiva. Agregar / eliminar la IDENTITYpropiedad en una columna, por ejemplo.
Aaron Bertrand
2
Agregar una nueva columna al final de los campos que es NULLABLE no requiere una reconstrucción de la tabla.
PseudoToad
2

Sí, hay efectos negativos de esto:

Si escribe un cambio bloqueado por este indicador, obtendrá algo como el siguiente script (todo lo que estoy haciendo es convertir la columna de ID en Contacto en una columna de IDENTIDAD autonumerada, pero la tabla tiene dependencias). Tenga en cuenta los posibles errores que pueden ocurrir mientras se ejecuta lo siguiente:

  1. ¡Incluso Microsoft advierte que esto puede causar la pérdida de datos (ese comentario se genera automáticamente)!
  2. por un período de tiempo, las claves foráneas no se aplican.
  3. si ejecuta esto manualmente en ssms y 'EXEC (' INSERT INTO 'falla, y deja que se ejecuten las siguientes instrucciones (lo que hacen de manera predeterminada, ya que están divididas por' go '), entonces insertará 0 filas y luego soltará La vieja mesa.
  4. Si esta es una tabla grande, el tiempo de ejecución de la inserción puede ser grande y la transacción contiene un bloqueo de modificación de esquema, por lo que bloquea muchas cosas.

-

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