2189 votes

Comment vérifier si une colonne existe dans une table SQL Server

Je dois ajouter une colonne spécifique si elle n'existe pas. J'ai quelque chose comme ci-dessous, mais cela renvoie toujours faux:

IF EXISTS(SELECT *
          FROM   INFORMATION_SCHEMA.COLUMNS
          WHERE  TABLE_NAME = 'myTableName'
                 AND COLUMN_NAME = 'myColumnName') 

Comment puis-je vérifier si une colonne existe dans une table de la base de données SQL Server?

18 votes

Je ne pense pas qu'il y ait quelque chose de mal avec le code dans la question : Ça fonctionne bien pour moi en 2008 R2. (Peut-être que vous l'exécutez dans la mauvaise base de données ? Peut-être que votre base de données est sensible à la casse et que vous n'avez pas la bonne casse dans vos chaînes myTableName / myColumnName ? Ce type de requête semble plus flexible que la solution COL_LENGTH : je peux l'exécuter sur une base de données différente et même sur un lien de base de données en préfixant correctement " INFORMATION_SCHEMA ". Je ne voyais pas comment faire cela avec la fonction de métadonnées COL_LENGTH.

4 votes

@mwardm - COL_LENGTH('AdventureWorks2012.RessourcesHumaines.Department ','ModifiedDate') fonctionne correctement.

7 votes

Petit conseil lié : si vous souhaitez mettre à jour une colonne juste après son ajout (je pense que de nombreux utilisateurs recherchaient cet article à cette fin), vous pourriez utiliser EXEC sp_executesql avec une déclaration de UPDATE formée.

2386voto

Mitch Wheat Points 169614

À partir de SQL Server 2005 :

IF EXISTS(SELECT 1 FROM sys.columns 
          WHERE Name = N'nomDeLaColonne'
          AND Object_ID = Object_ID(N'schemaName.nomTable'))
BEGIN
    -- La colonne existe
END

La version de Martin Smith est plus courte :

IF COL_LENGTH('schemaName.nomTable', 'nomDeLaColonne') IS NOT NULL
BEGIN
    -- La colonne existe
END

4 votes

Dans la version de Martin Smith, une chose à mentionner est de ne pas inclure le nom de la colonne dans des crochets [ ]. Lorsque le nom de la colonne est à l'intérieur de crochets [ ], il renverra null même si la colonne existe dans la table

0 votes

@HemendraSinghChauhan - c'est parce qu'ils ne font pas partie du nom. Vous constaterez également que lors de la comparaison avec le nom dans sys.columns

0 votes

@MartinSmith ne savait pas ça, j'utilisais votre réponse et je suis tombé là-dessus. En général, j'utilise des crochets carrés lors de l'ajout de colonnes, donc je les ai aussi utilisés dans la fonction COL_LENGTH. Mon code était comme ceci: Alter table Table_Name Add [ColumnName] NVarchar(max) NULL; Select COL_LENGTH('[TABLE_NAME]', '[COLUMN_NAME]')

1167voto

Martin Smith Points 174101

Une version plus concise

SI COL_LONGUEUR('nom_table','nom_colonne') IS NULL
DÉBUT
/* La colonne n'existe pas ou l'appelant n'a pas la permission de voir l'objet */
FIN

Le point concernant les autorisations pour afficher les métadonnées s'applique à toutes les réponses, pas seulement à celle-ci.

Notez que le premier paramètre nom de table de COL_LONGUEUR peut être au format un, deux ou trois parties, selon les besoins.

Un exemple faisant référence à une table dans une base de données différente est :

COL_LONGUEUR('AdventureWorks2012.RessourcesHumaines.Service','DateModification')

Une différence avec cette réponse, par rapport à l'utilisation des vues sur les métadonnées, est que les fonctions de métadonnées, telles que COL_LONGUEUR, ne renvoient toujours que des données sur des modifications validées, quel que soit le niveau d'isolation en cours.

15 votes

Ceci est moins lisible que certaines des autres réponses, c'est probablement pourquoi elle n'est pas aussi bien notée.

46 votes

@Bill - Moins lisible de quelle manière ? Ça semble bien dans Firefox. Cette réponse a été postée plus de 2 ans après celle acceptée, ce qui explique la notation à mon avis. Si vous vouliez dire moins clair que c'est une vérification d'existence, ce type d'idiome est assez commun dans SQL Server. par exemple en utilisant IF OBJECT_ID('TableName','U') IS NULL pour vérifier l'existence de l'objet ou DB_ID('foo') pour vérifier l'existence de la base de données.

71 votes

@MartinSmith Je suis sûr qu'il voulait dire moins lisible parce que si vous ne connaissiez pas cet idiome et que vous avez hérité de ce code de quelqu'un d'autre, vous ne comprendriez pas immédiatement ce que fait le code. Un peu comme écrire x>>2 au lieu de x/4 en C++. Le code plus verbeux (if exists (select column_name from information_schema ...)) prend beaucoup plus de place, mais personne ne se gratterait jamais la tête en essayant de comprendre ce qu'il fait.

179voto

Luke Bennett Points 16100

Ajustez ce qui suit pour répondre à vos besoins spécifiques :

if not exists (select
                     column_name
               from
                     INFORMATION_SCHEMA.columns
               where
                     table_name = 'MyTable'
                     and column_name = 'MyColumn')
    alter table MyTable add MyColumn int

Cela devrait fonctionner - examinez attentivement votre code pour rechercher des erreurs stupides; interrogez-vous par exemple sur INFORMATION_SCHEMA dans la même base de données que votre insertion est appliquée? Avez-vous une faute de frappe dans le nom de votre table/colonne dans l'une ou l'autre instruction?

6 votes

Je viens de découvrir que l'ajout de TABLE_SCHEMA = 'mySchema' après la clause where corrige le problème.

13 votes

-1: ne répond pas à la question de l'OP, ajoute uniquement de nouvelles informations sur la façon d'ajouter une nouvelle colonne malgré le fait que l'OP n'ait pas du tout posé de question à ce sujet, ne répond pas au commentaire de l'OP.

4 votes

+1 Répond parfaitement à la question de l'OP avec en prime les informations supplémentaires que l'OP cherchait de toute façon. Et c'était exactement ce que je cherchais.

91voto

Leon Tayson Points 1837

Essayez ceci...

IF NOT EXISTS(
  SELECT TOP 1 1
  FROM INFORMATION_SCHEMA.COLUMNS
  WHERE 
    [TABLE_NAME] = 'Employees'
    AND [COLUMN_NAME] = 'EmployeeID')
BEGIN
  ALTER TABLE [Employees]
    ADD [EmployeeID] INT NULL
END

6 votes

Cette méthode fonctionne également avec SQL CE, alors que certaines des autres méthodes mentionnées ne le font pas.

9 votes

Vous pouvez utiliser SELECT 1 au lieu de SELECT TOP 1 1 ;).

6 votes

Au sein d'une instruction EXISTS, SQL optimise automatiquement les colonnes (tout comme count(*)), donc SELECT * sera suffisant.

50voto

Christian Hayter Points 17999

Je préfère INFORMATION_SCHEMA.COLUMNS à une table système car Microsoft ne garantit pas la préservation des tables systèmes entre les versions. Par exemple, dbo.syscolumns fonctionne toujours dans SQL Server 2008, mais il est obsolète et pourrait être supprimé à tout moment à l'avenir.

7 votes

Eh bien oui, cela va sans dire puisque les vues INFORMATION_SCHEMA contiennent uniquement des métadonnées conformes à la norme ANSI. Cependant, cela suffit pour un test d'existence.

4 votes

Microsoft dit "Dans les futures versions de SQL Server, Microsoft peut compléter la définition de toute vue de catalogue système en ajoutant des colonnes à la fin de la liste des colonnes. Nous déconseillons l'utilisation de la syntaxe SELECT * FROM nom_vue_catalogue_sys dans le code de production car le nombre de colonnes renvoyées pourrait changer et casser votre application." Cela implique qu'ils ne supprimeront pas de colonnes ou ne changeront pas leur ordre. C'est une compatibilité ascendante suffisante pour tous sauf les cas marginaux.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X