{"id":221,"date":"2011-05-30T00:00:12","date_gmt":"2011-05-30T00:00:12","guid":{"rendered":"http:\/\/www.sqlserver.fr\/blog\/?p=221"},"modified":"2026-05-02T14:31:20","modified_gmt":"2026-05-02T12:31:20","slug":"ajout-de-colonne","status":"publish","type":"post","link":"https:\/\/www.sqlserver.fr\/blog\/ajout-de-colonne\/","title":{"rendered":"Ajout de colonne"},"content":{"rendered":"<p>M\u00eame si l\u2019on essaie toujours de viser juste du premier coup, un mod\u00e8le de donn\u00e9es n\u2019est jamais complet \u00e0 la premi\u00e8re impl\u00e9mentation, et il peut notamment arriver que l\u2019on ait besoin de rajouter certaines colonnes \u00e0 des tables d\u00e9j\u00e0 remplies. Et lorsqu\u2019il s\u2019agit de colonnes non Nullables et que l\u2019on souhaite formaliser la modification sous forme de script, quelques bonnes pratiques sont \u00e0 conna\u00eetre.<!--more--><br \/>\nLorsque l\u2019on bricole un peu dans son coin et que l\u2019on cherche \u00e0 ajouter une colonne \u00e0 une table existante, on ne s\u2019emb\u00eate en g\u00e9n\u00e9ral pas trop et on utilise l\u2019interface de SQL Server Management Studio (SSMS). Mais dans un d\u00e9veloppement professionnel, tout se fait par script, afin de pouvoir \u00eatre rejouer \u00e0 l\u2019identique sur chaque environnement (tests, production, \u2026).<br \/>\nPla\u00e7ons-nous par exemple sur SQL Server 200R2, sur la base d\u2019exemple AventureWorks2008R2, que l\u2019on peut trouver ici : <a href=\"https:\/\/github.com\/Microsoft\/sql-server-samples\/releases\/tag\/adventureworks\">http:\/\/msftdbprodsamples.codeplex.com\/<\/a><br \/>\nSupposons que l\u2019on cherche \u00e0 rajouter une colonne ModifiedDate, non nullable, dans la table DatabaseLog.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">ALTER TABLE dbo.DatabaseLog\r\n\tADD ModifiedDate datetime NOT NULL<\/pre>\n<p><span style=\"font-size: small;\">Le probl\u00e8me est que cet ajout n\u2019est pas autoris\u00e9 en l\u2019\u00e9tat :<\/span><br \/>\n<span style=\"font-size: x-small;\">Msg 4901, Niveau 16, \u00c9tat 1, Ligne 1<\/span><br \/>\n<span style=\"font-size: x-small;\">ALTER TABLE permet d&rsquo;ajouter uniquement des colonnes pouvant contenir des valeurs NULL, des colonnes ayant une d\u00e9finition DEFAULT, des colonnes identit\u00e9 ou de type timestamp ; si aucune des conditions pr\u00e9c\u00e9dentes n&rsquo;est satisfaite, la table doit \u00eatre vide pour autoriser l&rsquo;ajout de cette colonne. La colonne &lsquo;ModifiedDate&rsquo; ne peut pas \u00eatre ajout\u00e9e \u00e0 une table non vide &lsquo;DatabaseLog&rsquo; car elle ne r\u00e9pond pas \u00e0 ces conditions.<\/span><\/p>\n<p>ALTER TABLE permet d&rsquo;ajouter uniquement des colonnes pouvant contenir des valeurs NULL, des colonnes ayant une d\u00e9finition DEFAULT, des colonnes identit\u00e9 ou de type timestamp ; si aucune des conditions pr\u00e9c\u00e9dentes n&rsquo;est satisfaite, la table doit \u00eatre vide pour autoriser l&rsquo;ajout de cette colonne. La colonne &lsquo;ModifiedDate&rsquo; ne peut pas \u00eatre ajout\u00e9e \u00e0 une table non vide &lsquo;DatabaseLog&rsquo; car elle ne r\u00e9pond pas \u00e0 ces conditions.<br \/>\nEffectivement, c\u2019est tout \u00e0 faire compr\u00e9hensible. Quelle serait la valeur de cette colonne pour les enregistrements existants ?<br \/>\nChoisissons donc par exemple de mettre 01\/01\/2001 en valeur par d\u00e9faut.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">ALTER TABLE dbo.DatabaseLog\r\n\tADD ModifiedDate datetime NOT NULL DEFAULT '20010101'<\/pre>\n<p>Premi\u00e8re \u00e9tape, OK. Mais maintenant, il faudrait peut-\u00eatre revenir \u00e0 notre objectif, c\u2019est-\u00e0-dire de cr\u00e9er une colonne non nullable. Il faut donc supprimer la \u00ab contrainte \u00bb DEFAULT que nous avons mise en place.<br \/>\n<a href=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image001.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-222\" title=\"image001\" src=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image001.jpg\" alt=\"\" width=\"386\" height=\"381\" srcset=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image001.jpg 386w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/03\/image001-300x296.jpg 300w\" sizes=\"auto, (max-width: 386px) 100vw, 386px\" \/><\/a><br \/>\nOn s\u2019aper\u00e7oit que le syst\u00e8me a automatiquement fix\u00e9 un nom pour la contrainte (commen\u00e7ant par DF, puisqu\u2019il s\u2019agit d\u2019une contrainte DEFAULT, et contenant le d\u00e9but du nom de la table et du nom de la colonne). Et ce nom se termine par un identifiant al\u00e9atoire, qui ici nous pose bien probl\u00e8me. En effet, nous avons pour objectif de supprimer cette contrainte, et cela devient probl\u00e9matique si le nom est al\u00e9atoire\u2026<br \/>\nEn fait, l\u2019erreur vient du script via lequel nous avons ajout\u00e9 la colonne. C\u2019\u00e9tait le moment (ou jamais) de fixer un nom pour la colonne.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">ALTER TABLE dbo.DatabaseLog\r\n\tADD ModifiedDate datetime NOT NULL CONSTRAINT DF_DatabaseLog_ModifiedDate DEFAULT '20010101'<\/pre>\n<p>Maintenant, il devient beaucoup plus facile de supprimer la contrainte, puisque nous en connaissons le nom.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">ALTER TABLE dbo.DatabaseLog\r\n\tDROP CONSTRAINT DF_DatabaseLog_ModifiedDate<\/pre>\n<p>Donc voici la petite astuce : lorsque l\u2019on rajoute une contrainte, il convient de toujours la nommer, afin de pouvoir la contr\u00f4ler par la suite. Cette bonne pratique est aussi vraie pour les autres contraintes (cl\u00e9s primaires, Check, \u2026)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>M\u00eame si l\u2019on essaie toujours de viser juste du premier coup, un mod\u00e8le de donn\u00e9es n\u2019est jamais complet \u00e0 la premi\u00e8re impl\u00e9mentation, et il peut notamment arriver que l\u2019on ait besoin de rajouter certaines colonnes \u00e0 des tables d\u00e9j\u00e0 remplies. &hellip; <a href=\"https:\/\/www.sqlserver.fr\/blog\/ajout-de-colonne\/\">Continuer la lecture <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-221","post","type-post","status-publish","format-standard","hentry","category-article_sql"],"_links":{"self":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/221","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/comments?post=221"}],"version-history":[{"count":7,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/221\/revisions"}],"predecessor-version":[{"id":1963,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/221\/revisions\/1963"}],"wp:attachment":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/media?parent=221"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/categories?post=221"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/tags?post=221"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}