Ajouter une colonne à une table, si elle n'existe pas déjà


195

Je veux écrire une requête pour MS SQL Server qui ajoute une colonne dans une table. Mais je ne veux aucun affichage d'erreur lorsque j'exécute / exécute la requête suivante.

J'utilise ce type de requête pour ajouter une table ...

IF EXISTS (
       SELECT *
       FROM   sys.objects
       WHERE  OBJECT_ID = OBJECT_ID(N'[dbo].[Person]')
              AND TYPE IN (N'U')
   )

Mais je ne sais pas comment écrire cette requête pour une colonne.



Vous devriez utiliser à la sys.tablesplace du "générique" sys.objects- alors vous n'avez pas à spécifier le type explicitement (c'est évident du sys.tablesdéjà ....)
marc_s

COL_LENGTH Alternative fonctionne uniquement à partir de SQL-Server 2008, mais cela fonctionne.
Paul-Henri

@MartinSmith PAS un double de cela. Votre lien est un moyen possible de le résoudre (et en fait, c'est le moyen recommandé, en ce moment). Mais la question est en fait différente et d'autres solutions pourraient être disponibles (par exemple si SQL ajoute une IF NOT EXISTSclause à la ADD COLUMNsyntaxe)
Brondahl

@Brondahl - car la question a survécu au cours des 8,5 ans depuis la publication du commentaire auquel vous répondez n'a probablement pas besoin de paniquer. Pour le moment, toutes les réponses ici sont essentiellement des dupes de celles du Q lié
Martin Smith

Réponses:


226

Vous pouvez utiliser une construction similaire en utilisant la sys.columnstable io sys.objects.

IF NOT EXISTS (
  SELECT * 
  FROM   sys.columns 
  WHERE  object_id = OBJECT_ID(N'[dbo].[Person]') 
         AND name = 'ColumnName'
)

43
Notez que dans ce cas, vous souhaitez utiliser IF NOT EXISTS dans votre code réel.
Nat

2
Pour une requête optimisée, vous pouvez utiliser le top 1 avec l'instruction select
Banketeshvar Narayan

12
@BanketeshvarNarayan c'est incorrect. Les plans d'exécution des sous-requêtes dans une EXISTSclause sont identiques. Des choses comme SELECT 1ou SELECT TOP 1sont inutiles. La EXISTSclause elle-même indique à l'optimiseur de requêtes de n'effectuer que les lectures minimales nécessaires pour évaluer le EXISTS... au moins dans SQL Server. D'autres moteurs de base de données peuvent avoir un optimiseur de requêtes plus ou moins efficace.
Kenneth Cochran

10
@BanketeshvarNarayan Si vous optimisez vos ADD Columnrequêtes ... vous devez les exécuter trop souvent!
Fenton

1
@ user391339 - J'ai publié une construction similaire à celle publiée par OP, mais oui, si vous voulez prendre des mesures si la colonne n'existe pas , l'instruction serait IF NOT EXISTS. Je ne ressens pas vraiment le besoin de modifier la réponse pour cela, mais n'hésitez pas à modifier vous-même si vous pensez que c'est une amélioration.
Lieven Keersmaekers

98
IF COL_LENGTH('table_name', 'column_name') IS NULL
BEGIN
    ALTER TABLE table_name
    ADD [column_name] INT
END

1
J'ai essayé de faire celui-ci mais cela renvoie une erreur indiquant que la fonction COL_LENGTH n'existe pas.
ThEpRoGrAmMiNgNoOb

3
Requiert SQL Server 2008+
Robert Brown

7
Petit ajout - il ne faut pas utiliser de crochets dans le nom de la colonne, car COL_LENGTH('table_name', '[column_name]')il renvoie toujours null dans SQL Server 2016 ( COL_LENGTH('[table_name]', 'column_name') works as expected).
stop-cran

34

Une autre alternative. Je préfère cette approche car elle est moins écrite mais les deux accomplissent la même chose.

IF COLUMNPROPERTY(OBJECT_ID('dbo.Person'), 'ColumnName', 'ColumnId') IS NULL
BEGIN
    ALTER TABLE Person 
    ADD ColumnName VARCHAR(MAX) NOT NULL
END

J'ai également remarqué que le vôtre cherchait où la table existe qui est évidemment juste ceci

 if COLUMNPROPERTY( OBJECT_ID('dbo.Person'),'ColumnName','ColumnId') is not null

2
Je l'aime. Je pense que la meilleure partie de la publication ici est de trouver des gemmes comme celle-ci.
JStead

4
Qu'est-ce que «ColumnId»?
Marius Stănescu

'ColumnId' est le nom de la propriété de colonne que vous comparez. Vous auriez probablement pu utiliser n'importe quel nom de propriété existant sur une colonne, tel que name, etc.
Jacques Bosch

6

Voici une autre variante qui a fonctionné pour moi.

IF NOT EXISTS (SELECT 1
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE upper(TABLE_NAME) = 'TABLENAME'
        AND upper(COLUMN_NAME) = 'COLUMNNAME')
BEGIN
    ALTER TABLE [dbo].[Person] ADD Column
END
GO

MODIFIER: Notez que les INFORMATION_SCHEMAvues ne sont pas toujours mises à jour, utilisez à la SYS.COLUMNSplace:

IF NOT EXISTS (SELECT 1 FROM SYS.COLUMNS....


0
IF NOT EXISTS (SELECT 1  FROM SYS.COLUMNS WHERE  
OBJECT_ID = OBJECT_ID(N'[dbo].[Person]') AND name = 'DateOfBirth')
BEGIN
ALTER TABLE [dbo].[Person] ADD DateOfBirth DATETIME
END


0

Lors de la recherche d'une colonne dans une autre base de données, vous pouvez simplement inclure le nom de la base de données:

IF NOT EXISTS (
  SELECT * 
  FROM   DatabaseName.sys.columns 
  WHERE  object_id = OBJECT_ID(N'[DatabaseName].[dbo].[TableName]') 
         AND name = 'ColumnName'
)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.