11
votes

SQL Server alter le champ non nul prend pour toujours

Je veux modifier un champ d'une table qui compte environ 4 millions d'enregistrements. Je suis assuré que tous ces champs valeurs ne sont pas nuls et que vous souhaitez modifier ce champ pour NON NULL

ALTER TABLE dbo.MyTable
ALTER COLUMN myColumn int NOT NULL


4 commentaires

Personnellement, je ne changerais jamais une structure de table dans une grande table existante à tout moment, à l'exception des heures de pointe. Même si c'est assez rapide, cela peut provoquer des utilisateurs dans le processus de faire des choses à l'exercice que vous apportez le changement pour avoir des problèmes. Tout changement majeur est le mieux fait en mode utilisateur unique également. Bien mieux d'avoir une période de maintenance planifiée de sortie noirée lorsque les utilisateurs ne peuvent rien faire (annoncé à l'avance bien sûr et pendant les heures de pointe), que d'avoir des utilisateurs malheureux qui étaient en train de faire quelque chose qui reçoit des erreurs.


La colonne est-elle impliquée dans les contraintes FK?


D'un test rapide dans le profileur, il prend un SCH-M verrouillage sur la table qui est fondamentalement incompatible avec tout . Il doit ensuite lire chaque page pour déterminer que toutes les lignes valident.


Est la colonne int avant le changement?


3 Réponses :


4
votes

Vous pouvez modifier un champ et le rendre non nul sans qu'il vérifie les champs. Si vous êtes vraiment préoccupé par ne pas le faire hors heures, vous pouvez ajouter une contrainte au champ qui vérifie que ce n'est pas nul. Cela vous permettra d'utiliser l'option sans chèque, et de ne pas avoir vérifiant chacune des 4 millions de lignes pour voir si elle est mise à jour.

CREATE TABLE Test
(
    T0 INT Not NULL,
    T1 INT NUll 
)

INSERT INTO Test VALUES(1, NULL) -- Works!

ALTER TABLE Test
    WITH NOCHECK
        ADD CONSTRAINT N_null_test CHECK (T1 IS NOT NULL)

    ALTER COLUMN T1 int NOT NULL 

INSERT INTO Test VALUES(1, NULL) -- Doesn't work now!


4 commentaires

Si vous n'utilisez aucun chèque, la contrainte ne sera pas approuvée et ne peut pas être utilisée par l'optimiseur de requête. Voir SQLBLOG.com/blogs / tibor_karaszi / archive / 2008/01 / 12 / ...


En outre, le mot-clé NOCHECK ne s'applique pas à NULL / NOT NULL. Cela ne s'applique qu'aux contraintes qui font partie de la clause de contrainte.


À partir de la question, l'OP a déjà veillé à ce que leur colonne ne contienne aucun NULL ne soit pas sûr de la pertinence de la 2e partie de votre réponse?


@Martin, il a peut-être assuré, mais la personne suivante lisant la réponse peut ne pas. C'est une petite quantité d'espace pour couvrir l'autre scénario et si l'OP a commis une erreur et a des valeurs nulles, il dispose de plus d'informations pour prendre une décision.



2
votes

Désolé pour le découragement, mais:


0 commentaires

4
votes

Le seul moyen de faire cela "rapidement" (*) que je connais est par

  • Création d'une table 'Shadow' qui a la mise en page requise
  • Ajout d'une gâchette à la table source afin de copier des opérations d'insertion / mise à jour / Supprimer des opérations d'ombre (esprit pour attraper n'importe quel null qui pourrait popup!)
  • Copiez toutes les données de la source à la table Shadow, potentiellement en petits morceaux (assurez-vous de pouvoir gérer les données déjà copiées par la ou les déclencheurs, assurez-vous que les données s'assurent dans la nouvelle structure (ISNULL ( ?)!)
  • script sur toutes les dépendances de / vers d'autres tables
  • Quand tout est fait, procédez comme suit dans une transaction explicite:
    • Obtenez une serrure de table exclusive sur la table source et une sur la Shadowtable
    • Exécutez les scripts pour déposer des dépendances à la table source
    • renommer la table source à quelque chose d'autre (suffixe par exemple _old)
    • Renommez la table d'ombre au nom original de la table source
    • Exécutez les scripts pour créer à nouveau toutes les dépendances

      Vous voudrez peut-être faire la dernière étape en dehors de la transaction, car cela pourrait prendre un peu de temps en fonction de la quantité et de la taille des tables faisant référence à cette table, les premières étapes ne prendront pas beaucoup de temps sur tout

      Comme toujours, il est probablement préférable de faire un test d'essai sur un serveur de test d'abord =)

      PS: N'ayez pas tenté de recréer le FK avec NoCheck, il les rend futiles à mesure que l'optimiseur ne leur fera pas confiance ni les considère que lors de la construction d'un plan de requête.

      (*: où est rapidement descendu à: avec le moins de temps d'arrêt possible)


1 commentaires

Je jouais avec cette idée depuis la semaine dernière, mais dans notre situation spécifique, nous avons constaté des problèmes car il pourrait y avoir plusieurs changements de colonne qui ne se connaissent pas les uns des autres, la création de manière dynamique de "au lieu de" des déclencheurs serait impossible est tout à être automatisé). Ce matin, cela m'est arrivé que cela pourrait être axé sur la table et j'allais poster la réponse ici uniquement pour trouver que vous me battiez à cela :)