1960

I need to add a specific column if it does not exist. I have something like the following, but it always returns false:

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

How can I check if a column exists in a table of the SQL Server database?

Rann Lifshitz
  • 3,862
  • 4
  • 18
  • 40
Maciej
  • 19,978
  • 3
  • 18
  • 23
  • 15
    I don't actually think there's anything wrong with the code in the question: Works finely for me in 2008 R2. (Maybe you were running it in the wrong database? Maybe your database was case-sensitive and you didn't have the case right in your myTableName / myColumnName strings? This type of query seems more flexible than the COL_LENGTH solution: I'm able to run it against a different database and even over a database link by suitably prefixing "INFORMATION_SCHEMA". Couldn't see how to do that with the COL_LENGTH metadata-function. – mwardm Jun 13 '13 at 14:57
  • 4
    @mwardm - `COL_LENGTH('AdventureWorks2012.HumanResources.Department ','ModifiedDate')` works fine. – Martin Smith Sep 12 '13 at 16:38
  • 7
    Little related hint: if you want to update a column right after column addition(I believe many users were searching this article for that purpose), you could use `EXEC sp_executesql` with formed `UPDATE` statement. – cassandrad Apr 16 '15 at 15:02
  • 1
    The real answer is you should add the database you are checking against so it's `FROM [YourDatabase].INFORMATION_SCHEMA.COLUMNS` – Alex Kwitny Jun 25 '15 at 22:35
  • 1
    You can also use syscolumns and sysobjects very simply. – dcpking Aug 29 '20 at 04:02

31 Answers31

2175

SQL Server 2005 onwards:

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

Martin Smith's version is shorter:

IF COL_LENGTH('schemaName.tableName', 'columnName') IS NOT NULL
BEGIN
    -- Column Exists
END
Mitch Wheat
  • 280,588
  • 41
  • 444
  • 526
  • In Martin Smith's version, one thing to mention is not to include columnName within square brackets [ ]. When columnName is inside square brackets [ ], it'll give null even if the column exists in the table – Hemendra Jun 24 '19 at 07:57
  • @HemendraSinghChauhan - that's because they aren't part of the name. You will also find that when comparing with the name in `sys.columns` – Martin Smith Jun 24 '19 at 07:59
  • @MartinSmith didn't knew that, I was using your answer and came across this. Generally I use square brackets during adding columns, so I used them inside COL_LENGTH function too. My code was like this: `Alter table Table_Name Add [ColumnName] NVarchar(max) NULL; Select COL_LENGTH('[TABLE_NAME]', '[COLUMN_NAME]')` – Hemendra Jun 24 '19 at 08:08
  • yes that isn't valid. The arguments to `COL_LENGTH` need to be unquoted. It is theoretically possible for someone to create a column that does actually have a name of `[COLUMN_NAME]` - e.g. `CREATE TABLE #T([[COLUMN_NAME]]] INT); SELECT * FROM #T` and then it would be ambiguous if this was not the rule. – Martin Smith Jun 24 '19 at 08:12
  • Shorter version not wotking when field id varchar(max) = null – AlejandroDG Aug 13 '20 at 17:35
  • @AlejandroDG Can you provide an example? I would say, this claim is not true. – kapsiR Mar 09 '21 at 15:46
  • 2
    What is the point of copying answer of other person to your answer? – Wodzu Apr 14 '21 at 08:40
  • @Wodzu I don't know what the answer list looked like at the time it was posted, but now Martin's answer is over a dozen answers down from this accepted answer. I would not have gone that far down to find it. – BVernon May 23 '21 at 20:59
1040

A more concise version

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

The point about permissions on viewing metadata applies to all answers not just this one.

Note that the first parameter table name to COL_LENGTH can be in one, two, or three part name format as required.

An example referencing a table in a different database is

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

One difference with this answer compared to using the metadata views is that metadata functions such as COL_LENGTH always only return data about committed changes irrespective of the isolation level in effect.

Vadim Ovchinnikov
  • 10,848
  • 4
  • 43
  • 73
Martin Smith
  • 402,107
  • 79
  • 682
  • 775
  • 12
    This is less readable than some of the other answers, probably why it's not as highly rated. – Bill Yang Nov 30 '11 at 22:09
  • 40
    @Bill - Less readable in what way? Looks fine in Firefox. This answer was posted more than 2 years later than the accepted one, which explains the rating IMO. If you meant less clear that it is an existence check this type of idiom is quite common in SQL Server. e.g. using `IF OBJECT_ID('TableName','U') IS NULL` to check object existence or `DB_ID('foo')` to check database existence. – Martin Smith Nov 30 '11 at 22:31
  • 63
    @MartinSmith I'm sure he meant less readable because if you didn't know this idiom, and you inherited this code from someone else, you would not immediately understand what the code does. Kind of like writing `x>>2` instead of `x/4` in C++. The more verbose code (`if exists (select column_name from information_schema ...)`) takes a lot more space, but no one would ever scratch their head trying to figure out what it does. – Kip Aug 20 '13 at 16:49
  • 25
    Besides more concise this is a way faster solution. Accessing `INFORMATION_SCHEMA` views or `sys.columns` hits disk, while `COL_LENGTH` uses cached database metadata. – wqw Jan 13 '14 at 08:49
  • 8
    This is probably not the most highly rated answer because it was given 2.5 years after the other one. That's why I always check the dates when comparing the ratings on two answers. It takes a lot longer to overcome an answer that was given much earlier. ;) – Sean Feb 28 '14 at 19:35
  • 6
    "_Less readable_" problem solution: `IF COL_LENGTH('Incidente_Incidente','Id_NC_I ') IS NULL /* – Pablo Claus May 28 '14 at 12:53
  • 2
    The select solution requires additional column check for schema scenario. col_length can be used `col_length('schema.table', 'column')`. – Pasi Savolainen Sep 08 '14 at 13:08
  • 2
    @PasiSavolainen and it accepts three part naming as well. `db_name.schema_name.table_name`. I'll edit my answer to include that explicitly as the three upvotes [on this comment](http://stackoverflow.com/questions/133031/how-to-check-if-column-exists-in-sql-server-table#comment24720735_133031) indicates that not everyone realises... – Martin Smith Sep 08 '14 at 19:03
  • @Kip This is true, but in my experience the issue is mitigated by the code that inevitably follows: `ALTER TABLE my_table ADD column_name` :) Same with the `OBJECT_ID` method. If that code *doesn't* follow this use of the function, then perhaps some comments (or the expanded syntax in the original answer) is warranted. – bvoyelr Jan 29 '15 at 15:26
  • 1
    Just needed to use this across our whole fleet - I can confirm this works against SQL 2000 through 2014. – Mike Dec 01 '15 at 02:07
  • one thing is to make sure there's no square bracket [ ] in the column name as it gives null every time. – Hemendra Jun 24 '19 at 06:21
  • @HemendraSinghChauhan - no it doesn't. `CREATE TABLE dbo.Test([abc[]]123] int);select * from dbo.Test;SELECT COL_LENGTH('dbo.Test','abc[]123') ` – Martin Smith Jun 24 '19 at 06:29
  • @MartinSmith what I meant was that `SELECT COL_LENGTH('dbo.Test','[abc[]123]')` will give NULL. Putting entire columnName in square brackets, in COL_LENGTH gives NULL. – Hemendra Jun 24 '19 at 07:53
  • @HemendraSinghChauhan - that's because the open and closing square brackets aren't part of the name. You would also get the same thing if you tried `SELECT * FROM sys.columns WHERE name = '[abc[]]123]'` – Martin Smith Jun 24 '19 at 07:57
  • 1
    'table_name' should be replaced with 'Schema_name.table_name' – ob213 Jul 12 '19 at 15:17
  • @PabloClaus Having to put that comment sort of defeats the purpose of being more concise, and I really don't care about whether it's faster as someone else mentioned... I can't imagine any real scenario in the world where that's not negligible because no one is going to write this sort of statement in a loop. But I love being concise so I will totally use this is projects where I am in the one in charge. Will not use when working on other's projects though because I can already here the response "well this isn't consistent with the rest of our application" and that's basically the trump card. – BVernon May 23 '21 at 21:06
  • 1
    @BVernon It was a very old joke dude... – Pablo Claus May 25 '21 at 00:23
  • 1
    @PabloClaus Ah, good one. It went over my head apparently. :) – BVernon May 26 '21 at 01:13
154

Tweak the below to suit your specific requirements:

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

Edit to deal with edit to question: That should work - take a careful look over your code for stupid mistakes; are you querying INFORMATION_SCHEMA on the same database as your insert is being applied to for example? Do you have a typo in your table/column name in either statement?

Luke Bennett
  • 31,586
  • 3
  • 28
  • 55
  • 5
    I just found out that adding TABLE_SCHEMA = 'mySchema' after where clause fixes the problem. – Maciej Sep 25 '08 at 17:01
  • 13
    -1: does not answer OP's question, only adds the new information on how to add a new collumn despite OP not asking about that at all, does not address OP's comment. – ANeves thinks SE is evil Nov 02 '11 at 11:46
  • 2
    +1 Answers OP's question perfectly with a bonus of the additional information the OP was going for next anyways. And this was what I was looking for. – Bitterblue Nov 11 '19 at 11:07
77

Try this...

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
Soner Gönül
  • 91,172
  • 101
  • 184
  • 324
Leon Tayson
  • 4,287
  • 5
  • 33
  • 35
57

For the people who are checking the column existence before dropping it.

From SQL Server 2016 you can use new DIE statements instead of big IF wrappers

ALTER TABLE Table_name DROP COLUMN IF EXISTS Column_name
Abel
  • 52,738
  • 19
  • 137
  • 227
Pரதீப்
  • 85,687
  • 16
  • 112
  • 148
49

I'd prefer INFORMATION_SCHEMA.COLUMNS over a system table because Microsoft does not guarantee to preserve the system tables between versions. For example, dbo.syscolumns does still work in SQL 2008, but it's deprecated and could be removed at any time in future.

Christian Hayter
  • 29,333
  • 6
  • 65
  • 96
  • 8
    ["INFORMATION_SCHEMA views could be incomplete since they are not updated for all new features"](http://msdn.microsoft.com/en-us/library/ms186224.aspx) – onedaywhen Feb 26 '13 at 15:45
  • 7
    Well yes, that goes without saying since `INFORMATION_SCHEMA` views contain only ANSI-standard metadata. However, that is sufficient for an existence test. – Christian Hayter Feb 26 '13 at 17:15
  • 4
    Microsoft says "In future releases of SQL Server, Microsoft may augment the definition of any system catalog view by adding columns to the end of the column list. We recommend against using the syntax SELECT * FROM sys.catalog_view_name in production code because the number of columns returned might change and break your application." That implies that they won't remove columns or change their order. That's good enough backward compatibility for all but edge cases. – siride Jul 12 '13 at 21:26
43

You can use the information schema system views to find out pretty much anything about the tables you're interested in:

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

You can also interrogate views, stored procedures and pretty much anything about the database using the Information_schema views.

  • This is exactly what the questionnaire is using, he needed to know how to add the column if it did not exist. – Birel Mar 12 '20 at 13:46
36

Try something like:

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

Then use it like this:

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

It should work on both SQL Server 2000 & SQL Server 2005. Not sure about SQL Server 2008, but don't see why not.

shA.t
  • 15,232
  • 5
  • 47
  • 95
Matt Lacey
  • 64,328
  • 10
  • 87
  • 143
34

First check if the table/column(id/name) combination exists in dbo.syscolumns (an internal SQL Server table that contains field definitions), and if not issue the appropriate ALTER TABLE query to add it. For example:

IF NOT EXISTS ( SELECT  *
            FROM    syscolumns
            WHERE   id = OBJECT_ID('Client')
                    AND name = 'Name' ) 
ALTER TABLE Client
ADD Name VARCHAR(64) NULL
shA.t
  • 15,232
  • 5
  • 47
  • 95
mdb
  • 49,388
  • 10
  • 62
  • 62
28

A good friend and colleague of mine showed me how you can also use an IF block with SQL functions OBJECT_ID and COLUMNPROPERTY in SQL SERVER 2005+ to check for a column. You can use something similar to the following:

You can see for yourself here

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
  • 1,369
  • 1
  • 19
  • 43
  • 1
    And of course, if you are confident that the table exists, you can leave out the first part of the condition and check on `COLUMNPROPERTY` only. – Ruud Helderman Dec 12 '14 at 12:52
27
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
23

This worked for me in SQL 2000:

IF EXISTS 
(
    SELECT * 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE table_name = 'table_name' 
    AND column_name = 'column_name'
)
BEGIN
...
END
Joe M
  • 2,142
  • 3
  • 28
  • 60
22

Try this

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') 
Pரதீப்
  • 85,687
  • 16
  • 112
  • 148
Douglas Tondo
  • 221
  • 2
  • 2
  • You don't need `INFORMATION_SCHEMA.TABLES` and you don't filter columns for a specific table, So it sometimes will return more than one row for same column names in separate tables ;). – shA.t Jun 15 '15 at 12:34
19

I needed similar for SQL SERVER 2000 and, as @Mitch points out, this only works inm 2005+.

Should it help anyone else, this is what worked for me in the end:

if exists (
    select * 
    from 
        sysobjects, syscolumns 
    where 
        sysobjects.id = syscolumns.id 
        and sysobjects.name = 'table' 
        and syscolumns.name = 'column')
SuicideSheep
  • 4,542
  • 15
  • 54
  • 99
FrostbiteXIII
  • 893
  • 9
  • 21
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
Dale K
  • 16,372
  • 12
  • 37
  • 62
14
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;
DeanOC
  • 6,782
  • 6
  • 40
  • 52
Na30m
  • 221
  • 4
  • 11
11

A temp table version of the accepted answer:

if (exists(select 1 
             from tempdb.sys.columns  
            where Name = 'columnName'
              and Object_ID = object_id('tempdb..#tableName')))
begin
...
end
Community
  • 1
  • 1
crokusek
  • 4,655
  • 1
  • 39
  • 56
  • 1
    How is that different from the accepted answer? Would a temp table not work in the accepted answer? – John Saunders Jan 08 '15 at 01:24
  • 1
    Correct. The accepted answer does not work for temp tables because 'sys.columns' must be specified as 'tempdb.sys.columns' and the table name must be preceeded by 'tempdb..'. – crokusek Jan 08 '15 at 20:08
10
select distinct object_name(sc.id)
from syscolumns sc,sysobjects so  
where sc.name like '%col_name%' and so.type='U'
Uwe Keim
  • 36,867
  • 50
  • 163
  • 268
Nishad
  • 430
  • 1
  • 7
  • 19
8

Wheat's answer is good, but assumes you do not have any identical table name / column name pairs in any schema or database. To make it safe for that condition use this...

select *
from Information_Schema.Columns
where Table_Catalog = 'DatabaseName'
  and Table_Schema = 'SchemaName'
  and Table_Name = 'TableName'
  and Column_Name = 'ColumnName'
Daniel Barbalace
  • 1,049
  • 1
  • 16
  • 10
8

There are several ways to check the existence of a column. I would strongly recommend to use INFORMATION_SCHEMA.COLUMNS as it is created in order to communicate with user. Consider following tables:

 sys.objects
 sys.columns

and even some other access methods available to check system catalog.

Also, no need to use SELECT *, simply test it by NULL value

IF EXISTS(
           SELECT NULL 
           FROM INFORMATION_SCHEMA.COLUMNS
           WHERE
             TABLE_NAME = 'myTableName'
             AND COLUMN_NAME = 'myColumnName'
         ) 
Ali Elmi
  • 266
  • 3
  • 9
  • 1
    No matter even if you `SELECT *` with `EXISTS`, because when exists is used it doesn't really select all the rows and all the columns, internally it just checks for the existence and not actually checks for all rows and columns – Pawan Nogariya Nov 23 '18 at 08:55
7

Here is a simple script I use to manage addition of columns in the database:

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

In this example, the Name is the ColumnName to be added and Object_Id is the TableName

Brien Foss
  • 2,950
  • 3
  • 16
  • 29
UJS
  • 785
  • 1
  • 8
  • 16
7

One of the most simple and understandable solution is:

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
  • 1,449
  • 16
  • 31
5

Do something if column is not existing:

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

Do something if column is existing:

BEGIN
    IF (COL_LENGTH('[dbo].[Table]', 'Column ') IS NOT NULL)
    BEGIN
        //Do something
    END
END;
Jagjit Singh
  • 523
  • 8
  • 13
4

Below query can be used to check whether searched column exists or not in the table. We can take decision based on the searched result also as shown below.

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
  • 5,290
  • 8
  • 18
  • 37
3

Yet another variation...

SELECT 
  Count(*) AS existFlag 
FROM 
  sys.columns 
WHERE 
  [name] = N 'ColumnName' 
  AND [object_id] = OBJECT_ID(N 'TableName')
Bikramjeet Singh
  • 659
  • 1
  • 7
  • 21
Manuel Alves
  • 3,263
  • 1
  • 25
  • 20
3

Another contribute is the following sample that add the column if not exist.

    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

Hope it helps. Simone

Simone Spagna
  • 486
  • 1
  • 16
3
//Only checks
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
1

table -->script table as -->new windows - you have design script. check and find column name in new windows

arnav
  • 2,735
  • 1
  • 19
  • 19
1

Execute the below query to check if the column exists in the given table:

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
  • 913
  • 10
  • 8
1
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
  • 1,049
  • 2
  • 16
  • 23
0
IF EXISTS(SELECT 1 FROM sys.columns 
      WHERE Name = N'columnName'
      AND Object_ID = Object_ID(N'schemaName.tableName'))

This should be the fairly easier way and straight forward solution to this problem. I have used this multiple times for similar scenarios. It works like a charm, no doubts on that.

Ilangeeran
  • 71
  • 5