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

1853

J'ai besoin d'ajouter une colonne spécifique si elle n'existe pas. J'ai quelque chose comme ce qui suit, mais il 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?

Maciej
la source
12
Je ne pense pas vraiment qu'il y ait quelque chose de mal avec le code dans la question: Fonctionne très bien pour moi en 2008 R2. (Peut-être que vous l'exécutiez dans la mauvaise base de données? Peut-être que votre base de données était sensible à la casse et que vous n'aviez pas le cas dans vos chaînes myTableName / myColumnName? Ce type de requête semble plus flexible que la solution COL_LENGTH: je suis capable pour l'exécuter sur une autre base de données et même sur un lien de base de données en préfixant convenablement "INFORMATION_SCHEMA". Impossible de voir comment le faire avec la fonction de métadonnées COL_LENGTH.
mwardm
3
@mwardm - COL_LENGTH('AdventureWorks2012.HumanResources.Department ','ModifiedDate')fonctionne très bien.
Martin Smith
6
Petit indice connexe: si vous souhaitez mettre à jour une colonne juste après l'ajout de colonne (je pense que de nombreux utilisateurs recherchaient cet article à cette fin), vous pouvez l'utiliser EXEC sp_executesqlavec une UPDATEinstruction formée .
cassandrad
La vraie réponse est que vous devez ajouter la base de données que vous vérifiez afin qu'elle soitFROM [YourDatabase].INFORMATION_SCHEMA.COLUMNS
Alex Kwitny

Réponses:

2054

SQL Server 2005 et suivants:

IF EXISTS(SELECT 1 FROM sys.columns 
          WHERE Name = N'columnName'
          AND Object_ID = Object_ID(N'schemaName.tableName'))
BEGIN
    -- Column Exists
END

La version de Martin Smith est plus courte:

IF COL_LENGTH('schemaName.tableName', 'columnName') IS NOT NULL
BEGIN
    -- Column Exists
END
Blé Mitch
la source
Dans la version de Martin Smith, une chose à mentionner est de ne pas inclure columnName entre crochets []. Lorsque columnName est entre crochets [], cela donnera null même si la colonne existe dans le tableau
Hemendra
@HemendraSinghChauhan - c'est parce qu'ils ne font pas partie du nom. Vous constaterez également qu'en comparant avec le nom ensys.columns
Martin Smith
@MartinSmith ne le savait pas, j'utilisais votre réponse et je suis tombé sur cela. En général, j'utilise des crochets lors de l'ajout de colonnes, je les ai donc également utilisées 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]')
Hemendra
oui ce n'est pas valable. Les arguments COL_LENGTHdoivent être non cités. Il est théoriquement possible pour quelqu'un de créer une colonne qui a en fait un nom de [COLUMN_NAME]- par exemple, CREATE TABLE #T([[COLUMN_NAME]]] INT); SELECT * FROM #Tet ce serait ambigu si ce n'était pas la règle.
Martin Smith
987

Une version plus concise

IF COL_LENGTH('table_name','column_name') IS NULL
BEGIN
/* Column does not exist or caller does not have permission to view the object */
END

Le point concernant les autorisations sur l'affichage des métadonnées s'applique à toutes les réponses et pas seulement à celle-ci.

Notez que le premier nom de la table de paramètres à COL_LENGTH peut être au format de nom à une, deux ou trois parties selon les besoins.

Un exemple référençant une table dans une base de données différente est

COL_LENGTH('AdventureWorks2012.HumanResources.Department','ModifiedDate')

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

Martin Smith
la source
11
C'est moins lisible que certaines des autres réponses, probablement pourquoi ce n'est pas aussi bien noté.
Bill Yang
38
@Bill - Moins lisible de quelle manière? Ça va bien dans Firefox. Cette réponse a été postée plus de 2 ans plus tard que celle acceptée, ce qui explique la notation OMI. Si vous vouliez dire moins clairement qu'il s'agit d'un contrôle d'existence, ce type d'idiome est assez courant dans SQL Server. par exemple, utiliser IF OBJECT_ID('TableName','U') IS NULLpour vérifier l'existence d'un objet ou DB_ID('foo')pour vérifier l'existence d'une base de données.
Martin Smith
59
@MartinSmith Je suis sûr qu'il voulait dire moins lisible parce que si vous ne connaissiez pas cet idiome et que vous héritiez de ce code de quelqu'un d'autre, vous ne comprendriez pas immédiatement ce que fait le code. Un peu comme écrire x>>2au lieu de x/4C ++. Le code plus verbeux ( if exists (select column_name from information_schema ...)) prend beaucoup plus d'espace, mais personne ne se gratterait la tête en essayant de comprendre ce qu'il fait.
Kip
22
En plus d'être plus concis, c'est une solution beaucoup plus rapide. Accès aux INFORMATION_SCHEMAvues ou au sys.columnsdisque, tout en COL_LENGTHutilisant des métadonnées de base de données mises en cache.
wqw
7
Ce n'est probablement pas la réponse la mieux notée car elle a été donnée 2,5 ans après l'autre. C'est pourquoi je vérifie toujours les dates lorsque je compare les notes sur deux réponses. Il faut beaucoup plus de temps pour surmonter une réponse donnée beaucoup plus tôt. ;)
Sean
149

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

Modifier pour traiter la modification à la question : Cela devrait fonctionner - regardez attentivement votre code pour les erreurs stupides; par exemple, interrogez-vous INFORMATION_SCHEMA sur la même base de données que votre insert? Avez-vous une faute de frappe dans le nom de votre table / colonne dans l'une ou l'autre instruction?

Luke Bennett
la source
3
Je viens de découvrir que l'ajout de TABLE_SCHEMA = 'mySchema' après la clause where résout le problème.
Maciej
12
-1: ne répond pas à la question d'OP, ajoute uniquement les nouvelles informations sur la façon d'ajouter une nouvelle colonne bien qu'OP ne pose aucune question à ce sujet, ne répond pas au commentaire d'OP.
ANeves
1
+1 Répond parfaitement à la question du PO avec un bonus des informations supplémentaires que le PO recherchait de toute façon. Et c'est ce que je cherchais.
Bitterblue
74

Essaye ça...

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
Leon Tayson
la source
6
Cette méthode fonctionne également avec SQL CE, contrairement à certaines des autres méthodes mentionnées.
SWalters
9
Vous pouvez utiliser à la SELECT 1place de SELECT TOP 1 1;).
shA.t
4
Dans une EXISTSinstruction, SQL optimise automatiquement les colonnes (un peu comme count(*)), donc SELECT *cela suffira.
Marc L.
Par souci d'exhaustivité, vous devriez envisager d'ajouter and [TABLE_SCHEMA] = '???'à la clause WHERE.
Andrew Jens
51

Pour les personnes qui vérifient l'existence de la colonne de la supprimer.

À partir de SQL Server 2016, vous pouvez utiliser de nouvelles instructions DIE au lieu de gros IFwrappers

ALTER TABLE Table_name DROP COLUMN IF EXISTS Column_name
P ரதீப்
la source
47

Je préférerais INFORMATION_SCHEMA.COLUMNSune table système car Microsoft ne garantit pas de conserver les tables système entre les versions. Par exemple, dbo.syscolumnsfonctionne toujours dans SQL 2008, mais il est obsolète et pourrait être supprimé à tout moment à l'avenir.

Christian Hayter
la source
5
Eh bien oui, cela va de soi puisque les INFORMATION_SCHEMAvues ne contiennent que des métadonnées standard ANSI. Cependant, cela suffit pour un test d'existence.
Christian Hayter
3
Microsoft indique: "Dans les futures versions de SQL Server, Microsoft peut étendre la définition de tout affichage de catalogue système en ajoutant des colonnes à la fin de la liste des colonnes. Nous vous déconseillons d'utiliser la syntaxe SELECT * FROM sys.catalog_view_name dans le code de production car le nombre de les colonnes retournées peuvent changer et casser votre application. " Cela implique qu'ils ne supprimeront pas les colonnes ni ne modifieront leur ordre. C'est une compatibilité assez bonne pour tous les cas, sauf les cas de bord.
siride
42

Vous pouvez utiliser les vues du système de schéma d'informations pour découvrir à peu près tout sur les tables qui vous intéressent:

SELECT *
  FROM INFORMATION_SCHEMA.COLUMNS
 WHERE TABLE_NAME = 'yourTableName'
 ORDER BY ORDINAL_POSITION

Vous pouvez également interroger des vues, des procédures stockées et à peu près tout sur la base de données à l'aide des vues Information_schema.

anonyme
la source
C'est exactement ce que le questionnaire utilise, il avait besoin de savoir comment ajouter la colonne si elle n'existait pas.
Birel
35

Essayez quelque chose comme:

CREATE FUNCTION ColumnExists(@TableName varchar(100), @ColumnName varchar(100))
RETURNS varchar(1) AS
BEGIN
DECLARE @Result varchar(1);
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = @TableName AND COLUMN_NAME = @ColumnName)
BEGIN
    SET @Result = 'T'
END
ELSE
BEGIN
    SET @Result = 'F'
END
RETURN @Result;
END
GO

GRANT EXECUTE ON  [ColumnExists] TO [whoever]
GO

Ensuite, utilisez-le comme ceci:

IF ColumnExists('xxx', 'yyyy') = 'F'
BEGIN
  ALTER TABLE xxx
  ADD yyyyy varChar(10) NOT NULL
END
GO

Il devrait fonctionner à la fois sur SQL Server 2000 et SQL Server 2005. Vous n'êtes pas sûr de SQL Server 2008, mais vous ne voyez pas pourquoi.

Matt Lacey
la source
34

Vérifiez d'abord si la combinaison table/ column( id/ name) existe dans dbo.syscolumns(une table SQL Server interne qui contient des définitions de champ), et sinon lancez la ALTER TABLErequête appropriée pour l'ajouter. Par exemple:

IF NOT EXISTS ( SELECT  *
            FROM    syscolumns
            WHERE   id = OBJECT_ID('Client')
                    AND name = 'Name' ) 
ALTER TABLE Client
ADD Name VARCHAR(64) NULL
mdb
la source
28

Un bon ami et collègue m'a montré comment vous pouvez également utiliser un IFbloc avec des fonctions SQL OBJECT_IDet COLUMNPROPERTYdans SQL SERVER 2005+ pour rechercher une colonne. Vous pouvez utiliser quelque chose de similaire au suivant:

Vous pouvez voir par vous-même ici

IF (OBJECT_ID(N'[dbo].[myTable]') IS NOT NULL AND
    COLUMNPROPERTY( OBJECT_ID(N'[dbo].[myTable]'), 'ThisColumnDoesNotExist', 'ColumnId') IS NULL)
BEGIN
    SELECT 'Column does not exist -- You can add TSQL to add the column here'
END
brazilianldsjaguar
la source
1
Et bien sûr, si vous êtes certain que la table existe, vous pouvez laisser de côté la première partie de la condition et cocher COLUMNPROPERTYuniquement.
Ruud Helderman
26
declare @myColumn   as nvarchar(128)
set @myColumn = 'myColumn'
if not exists (
    select  1
    from    information_schema.columns columns 
    where   columns.table_catalog   = 'myDatabase'
        and columns.table_schema    = 'mySchema' 
        and columns.table_name      = 'myTable' 
        and columns.column_name     = @myColumn
    )
begin
    exec('alter table myDatabase.mySchema.myTable add'
    +'    ['+@myColumn+'] bigint       null')
end
Tuomo Kämäräinen
la source
22

Cela a fonctionné pour moi dans SQL 2000:

IF EXISTS 
(
    SELECT * 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE table_name = 'table_name' 
    AND column_name = 'column_name'
)
BEGIN
...
END
Joe M
la source
21

Essaye ça

SELECT COLUMNS.*
FROM   INFORMATION_SCHEMA.COLUMNS COLUMNS,
       INFORMATION_SCHEMA.TABLES TABLES
WHERE  COLUMNS.TABLE_NAME = TABLES.TABLE_NAME
       AND Upper(COLUMNS.COLUMN_NAME) = Upper('column_name') 
Douglas Tondo
la source
Vous n'avez pas besoin INFORMATION_SCHEMA.TABLESet vous ne filtrez pas les colonnes pour une table spécifique, il retournera donc parfois plus d'une ligne pour les mêmes noms de colonnes dans des tables séparées;).
shA.t
19

J'avais besoin de similaires pour SQL SERVER 2000 et, comme le souligne @Mitch, cela ne fonctionne que dans la version 2005+.

Si cela devait aider quelqu'un d'autre, c'est ce qui a finalement fonctionné pour moi:

if exists (
    select * 
    from 
        sysobjects, syscolumns 
    where 
        sysobjects.id = syscolumns.id 
        and sysobjects.name = 'table' 
        and syscolumns.name = 'column')
FrostbiteXIII
la source
15
if exists (
  select * 
  from INFORMATION_SCHEMA.COLUMNS 
  where TABLE_NAME = '<table_name>' 
  and COLUMN_NAME = '<column_name>'
) begin
  print 'Column you have specified exists'
end else begin
  print 'Column does not exist'
end
BYRAKUR SURESH BABU
la source
13
IF NOT EXISTS( SELECT NULL
            FROM INFORMATION_SCHEMA.COLUMNS
           WHERE table_name = 'TableName'
             AND table_schema = 'SchemaName'
             AND column_name = 'ColumnName')  BEGIN

  ALTER TABLE [SchemaName].[TableName] ADD [ColumnName] int(1) NOT NULL default '0';

END;
Na30m
la source
2
Je pense que vous vouliez dire table_schema = 'schema_name'.
Tab Alleman
11

Une version de table temporaire de la réponse acceptée :

if (exists(select 1 
             from tempdb.sys.columns  
            where Name = 'columnName'
              and Object_ID = object_id('tempdb..#tableName')))
begin
...
end
crokusek
la source
1
En quoi est-ce différent de la réponse acceptée? Une table temporaire ne fonctionnerait-elle pas dans la réponse acceptée?
John Saunders
1
Correct. La réponse acceptée ne fonctionne pas pour les tables temporaires car 'sys.columns' doit être spécifié comme 'tempdb.sys.columns' et le nom de la table doit être précédé de 'tempdb ..'.
crokusek
10
select distinct object_name(sc.id)
from syscolumns sc,sysobjects so  
where sc.name like '%col_name%' and so.type='U'
Nishad
la source
8

La réponse de Wheat est bonne, mais suppose que vous n'avez pas de paires nom de table / nom de colonne identiques dans un schéma ou une base de données. Pour le rendre sûr pour cette condition, utilisez ceci ...

select *
from Information_Schema.Columns
where Table_Catalog = 'DatabaseName'
  and Table_Schema = 'SchemaName'
  and Table_Name = 'TableName'
  and Column_Name = 'ColumnName'
Daniel Barbalace
la source
8

Il existe plusieurs façons de vérifier l'existence d'une colonne. Je recommanderais fortement de l'utiliser INFORMATION_SCHEMA.COLUMNStel qu'il est créé afin de communiquer avec l'utilisateur. Considérez les tableaux suivants:

 sys.objects
 sys.columns

et même d'autres méthodes d'accès disponibles pour vérifier system catalog.

Aussi, pas besoin d’utiliser SELECT *, testez-le simplementNULL value

IF EXISTS(
           SELECT NULL 
           FROM INFORMATION_SCHEMA.COLUMNS
           WHERE
             TABLE_NAME = 'myTableName'
             AND COLUMN_NAME = 'myColumnName'
         ) 
Ali Elmi
la source
1
Peu importe , même si vous SELECT *avec EXISTS, parce que quand il est utilisé EXISTE ne sélectionne pas vraiment toutes les lignes et toutes les colonnes, en interne , il vérifie seulement l'existence et non en fait des contrôles pour toutes les lignes et colonnes
Pawan Nogariya
7

L'une des solutions les plus simples et les plus compréhensibles est:

IF COL_LENGTH('Table_Name','Column_Name') IS NULL
 BEGIN
    -- Column Not Exists, implement your logic
 END 
ELSE
 BEGIN
    -- Column Exists, implement your logic
 END
Arsman Ahmad
la source
7

Voici un script simple que j'utilise pour gérer l'ajout de colonnes dans la base de données:

IF NOT EXISTS (
        SELECT *
        FROM sys.Columns
        WHERE Name = N'QbId'
            AND Object_Id = Object_Id(N'Driver')
        )
BEGIN
    ALTER TABLE Driver ADD QbId NVARCHAR(20) NULL
END
ELSE
BEGIN
    PRINT 'QbId is already added on Driver'
END

Dans cet exemple, le Nameest le ColumnNameà ajouter et Object_IdleTableName

UJS
la source
4

La requête ci-dessous peut être utilisée pour vérifier si la colonne recherchée existe ou non dans le tableau. Nous pouvons également prendre une décision en fonction du résultat de la recherche, comme indiqué ci-dessous.

IF EXISTS (SELECT 'Y' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = <YourTableName> AND COLUMN_NAME = <YourColumnName>)
  BEGIN
    SELECT 'Column Already Exists.'
  END
  ELSE
  BEGIN
    ALTER TABLE <YourTableName> ADD <YourColumnName> <DataType>[Size]
  END
Suraj Kumar
la source
3

Encore une autre variation ...

SELECT 
  Count(*) AS existFlag 
FROM 
  sys.columns 
WHERE 
  [name] = N 'ColumnName' 
  AND [object_id] = OBJECT_ID(N 'TableName')
Manuel Alves
la source
1

table -> table de script en tant que -> nouvelles fenêtres - vous avez un script de conception. vérifier et trouver le nom de la colonne dans de nouvelles fenêtres

Arnav
la source
1

Exécutez la requête ci-dessous pour vérifier si la colonne existe dans le tableau donné:

IF(SELECT COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'TableName' AND COLUMN_NAME = 'ColumnName') IS NOT NULL
PRINT 'Column Exists in the given table';
S Krishna
la source
1

Une autre contribution est l'exemple suivant qui ajoute la colonne si elle n'existe pas.

    USE [Northwind]
    GO

    IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS 
                    WHERE TABLE_NAME = 'Categories'
                        AND COLUMN_NAME = 'Note')
    BEGIN

    ALTER TABLE Categories ADD Note NVARCHAR(800) NULL

    END
    GO

J'espère que cela aide. Simone

Simone Spagna
la source
0
IF EXISTS(SELECT 1 FROM sys.columns 
      WHERE Name = N'columnName'
      AND Object_ID = Object_ID(N'schemaName.tableName'))

Cela devrait être la manière la plus simple et la solution directe à ce problème. Je l'ai utilisé plusieurs fois pour des scénarios similaires. Cela fonctionne comme un charme, aucun doute là-dessus.

Ilangeeran
la source
0
IF EXISTS (
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_CATALOG = 'Database Name'
and TABLE_SCHEMA = 'Schema Name'
and TABLE_NAME = 'Table Name'
and COLUMN_NAME = 'Column Name'
and DATA_TYPE = 'Column Type') -- Where statement lines can be deleted.

BEGIN
--COLUMN EXISTS IN TABLE
END

ELSE BEGIN
--COLUMN DOES NOT EXISTS IN TABLE
END
Mohamad Reza Shahrestani
la source
0

Faites quelque chose si la colonne n'existe pas:

BEGIN
    IF (COL_LENGTH('[dbo].[Table]', 'Column ') IS NULL)
    BEGIN
        //Do something
    END
END;

Faites quelque chose si la colonne existe:

BEGIN
    IF (COL_LENGTH('[dbo].[Table]', 'Column ') IS NOT NULL)
    BEGIN
        //Do something
    END
END;
Jagjit Singh
la source