«Empêcher l'enregistrement des modifications nécessitant la recréation de la table» effets négatifs

255

Préambule

Je modifiais une colonne dans SQL Server 2008 aujourd'hui, en changeant le type de données de quelque chose comme la devise (18,0) en (19,2).

J'ai reçu l'erreur «Les modifications que vous avez apportées nécessitent que les tables suivantes soient supprimées et recréées» de SQL Server.

Avant de vous précipiter pour répondre, veuillez lire ce qui suit:

Je sais déjà qu'il existe une option dans Outils ► Options ► Concepteur ► Concepteurs de tables et de bases de données ► Décochez la case "Empêcher l'enregistrement des modifications qui nécessitent une recréation de table". Empêcher l'enregistrement des modifications nécessitant une recréation de table en cinq clics ... alors ne répondez pas avec ça!

Question réelle

Ma vraie question est pour autre chose, comme suit:

Y a-t-il des effets négatifs / des inconvénients possibles à faire cela?

Le tableau est-il réellement supprimé et recréé automatiquement lorsque cette case n'est pas cochée?

Si oui, la table est-elle une réplique exacte à 100% de la table source?

CF_HoneyBadger
la source
65
Outils> Options> Designer ... c'est ce que je cherchais! Merci!
nrod
1
jetez également un œil à stackoverflow.com/questions/9870968/…
pylover
2
Et si vous êtes avec MS SQL Server 2014 -> Extras> Options> Designer Dans le menu supérieur.
Vityata

Réponses:

89

La table n'est supprimée et recréée que dans les cas où c'est la seule façon dont Management Studio de SQL Server a été programmé pour savoir comment le faire.

Il y a certainement des cas où il le fera quand il n'en aura pas besoin, mais il y aura aussi des cas où les modifications que vous apportez dans Management Studio ne seront pas supprimées et recréées car ce n'est pas nécessaire.

Le problème est qu'énumérer tous les cas et déterminer de quel côté de la ligne ils relèvent sera assez fastidieux.

C'est pourquoi j'aime utiliser ALTER TABLEdans une fenêtre de requête, au lieu des concepteurs visuels qui cachent ce qu'ils font (et très franchement ont des bugs) - je sais exactement ce qui va se passer, et je peux me préparer pour les cas où la seule possibilité consiste à supprimer et recréer la table (ce qui est un nombre inférieur à la fréquence à laquelle SSMS vous le fera).

Aaron Bertrand
la source
5
Bien qu'une très bonne réponse, je pense qu'elle ne fournit pas de réponses à toutes les questions soulevées par le PO, et ces questions sont celles qui m'intéressent, en fait. En particulier Y a-t-il des effets négatifs / des inconvénients possibles à faire cela? et Si oui, la table est-elle une réplique exacte à 100% de la table source? . Avez-vous des informations concernant ces questions?
tfrascaroli
252

Outils -> Options -> Noeud Designers -> Décochez " Empêcher l'enregistrement des modifications qui nécessitent une recréation de la table ".

Antoine Meltzheim
la source
12

Référence - La désactivation de cette option peut vous aider à éviter de recréer une table, elle peut également entraîner la perte des modifications. Par exemple, supposons que vous activez la fonctionnalité de suivi des modifications dans SQL Server 2008 pour suivre les modifications apportées à la table. Lorsque vous effectuez une opération qui entraîne la recréation de la table, vous recevez le message d'erreur mentionné dans la section "Symptômes". Toutefois, si vous désactivez cette option, les informations de suivi des modifications existantes sont supprimées lorsque la table est recréée. Par conséquent, Microsoft vous recommande de ne pas contourner ce problème en désactivant l'option.


la source
11

SQL Server supprime et recrée les tables uniquement si vous:

  • Ajouter une nouvelle colonne
  • Modifier le paramètre Autoriser les valeurs nulles pour une colonne
  • Modifier l'ordre des colonnes dans le tableau
  • Modifier le type de données de la colonne

L'utilisation d'ALTER est plus sûre, car si les métadonnées sont perdues pendant que vous recréez la table, vos données seront perdues.

Carol Baker West
la source
8
Votre liste n'est pas exhaustive. Ajoutez / supprimez la IDENTITYpropriété sur une colonne, par exemple.
Aaron Bertrand
2
L'ajout d'une nouvelle colonne à la fin des champs NULLABLE ne nécessite pas de reconstruction de table.
PseudoToad
2

Oui, cela a des effets négatifs:

Si vous scriptez une modification bloquée par cet indicateur, vous obtenez quelque chose comme le script ci-dessous (tout ce que je transforme la colonne ID dans Contact en une colonne IDENTITY numérotée automatiquement, mais la table a des dépendances). Notez les erreurs potentielles qui peuvent se produire lors de l'exécution des éléments suivants:

  1. Même Microsoft prévient que cela peut entraîner une perte de données (ce commentaire est généré automatiquement)!
  2. pendant un certain temps, les clés étrangères ne sont pas appliquées.
  3. si vous l'exécutez manuellement dans ssms et que 'EXEC (' INSERT INTO 'échoue, et que vous laissez les instructions suivantes s'exécuter (ce qu'elles font par défaut, car elles sont divisées par' go ')), vous insérerez 0 lignes, puis supprimerez l'ancienne table.
  4. s'il s'agit d'une grande table, le temps d'exécution de l'insertion peut être volumineux et la transaction contient un verrou de modification de schéma, ce qui bloque beaucoup de choses.

-

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