Мне нужно добавить конкретный столбец, если он не существует. У меня есть что-то вроде следующего, но он всегда возвращает false:

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

Как я могу проверить, существует ли столбец в таблице базы данных SQL Server?

2025
Maciej 25 Сен 2008 в 16:34
15
На самом деле я не думаю, что что-то не так с кодом в вопросе: у меня отлично работает в 2008 R2. (Возможно, вы запускали его в неправильной базе данных? Возможно, ваша база данных была чувствительна к регистру, и у вас не было правильного регистра в строках myTableName / myColumnName? Этот тип запроса кажется более гибким, чем решение COL_LENGTH: я могу чтобы запустить его в другой базе данных и даже по ссылке базы данных с помощью подходящего префикса «INFORMATION_SCHEMA». Не могу понять, как это сделать с помощью функции метаданных COL_LENGTH.
 – 
mwardm
13 Июн 2013 в 18:57
4
- COL_LENGTH('AdventureWorks2012.HumanResources.Department ','ModifiedDate') работает нормально.
 – 
Martin Smith
12 Сен 2013 в 20:38
7
Небольшая подсказка: если вы хотите обновить столбец сразу после добавления столбца (я полагаю, что многие пользователи искали эту статью для этой цели), вы можете использовать EXEC sp_executesql с сформированным оператором UPDATE.
 – 
cassandrad
16 Апр 2015 в 18:02
1
Настоящий ответ - вам следует добавить базу данных, по которой вы проверяете, чтобы она была FROM [YourDatabase].INFORMATION_SCHEMA.COLUMNS
 – 
Alex Kwitny
26 Июн 2015 в 01:35
1
Вы также можете очень просто использовать syscolumns и sysobjects.
 – 
dcpking
29 Авг 2020 в 07:02

30 ответов

Лучший ответ

SQL Server 2005 и более поздние версии:

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

Версия Мартина Смита короче:

IF COL_LENGTH('schemaName.tableName', 'columnName') IS NOT NULL
BEGIN
    -- Column Exists
END
2185
Mitch Wheat 12 Апр 2017 в 06:35
В версии Мартина Смита следует упомянуть одну вещь - не включать имя столбца в квадратные скобки []. Если имя столбца заключено в квадратные скобки [], будет возвращено значение null, даже если столбец существует в таблице.
 – 
Hemendra
24 Июн 2019 в 10:57
- это потому, что они не являются частью имени. Вы также обнаружите, что при сравнении с именем в sys.columns
 – 
Martin Smith
24 Июн 2019 в 10:59
Не знал этого, я использовал ваш ответ и наткнулся на это. Обычно при добавлении столбцов я использую квадратные скобки, поэтому я использовал их и внутри функции COL_LENGTH. Мой код был таким: Alter table Table_Name Add [ColumnName] NVarchar(max) NULL; Select COL_LENGTH('[TABLE_NAME]', '[COLUMN_NAME]')
 – 
Hemendra
24 Июн 2019 в 11:08
Да, это неверно. Аргументы для COL_LENGTH не должны заключаться в кавычки. Теоретически возможно создать столбец с именем [COLUMN_NAME], например CREATE TABLE #T([[COLUMN_NAME]]] INT); SELECT * FROM #T и тогда было бы двусмысленно, если бы это не было правилом.
 – 
Martin Smith
24 Июн 2019 в 11:12
Более короткая версия не работает, если идентификатор поля varchar (max) = null
 – 
AlejandroDG
13 Авг 2020 в 20:35

Более лаконичная версия

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

Пункт о разрешениях на просмотр метаданных относится ко всем ответам, а не только к этому.

Обратите внимание, что имя первой таблицы параметров для COL_LENGTH может быть в одно-, двух- или трехчастном формате имени по мере необходимости.

Пример ссылки на таблицу в другой базе данных:

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

Одно отличие этого ответа от использования представлений метаданных заключается в том, что функции метаданных, такие как COL_LENGTH, всегда возвращают данные только о зафиксированных изменениях независимо от действующего уровня изоляции.

1045
Vadim Ovchinnikov 22 Окт 2018 в 10:19
13
Это менее читабельно, чем некоторые другие ответы, возможно, поэтому он не так высоко оценен.
 – 
Bill Yang
1 Дек 2011 в 02:09
40
- Каким образом менее читабельно? Отлично смотрится в Firefox. Этот ответ был опубликован более чем на 2 года позже принятого, что объясняет рейтинг IMO. Если вы имели в виду менее ясно, что это проверка существования, этот тип идиомы довольно распространен в SQL Server. например использование IF OBJECT_ID('TableName','U') IS NULL для проверки существования объекта или DB_ID('foo') для проверки существования базы данных.
 – 
Martin Smith
1 Дек 2011 в 02:31
63
Я уверен, что он имел в виду менее читабельный, потому что, если бы вы не знали эту идиому и унаследовали этот код от кого-то другого, вы бы не сразу поняли, что делает этот код. Что-то вроде написания x>>2 вместо x/4 в C ++. Более подробный код (if exists (select column_name from information_schema ...)) занимает намного больше места, но никто бы никогда не стал чесать в затылке, пытаясь понять, что он делает.
 – 
Kip
20 Авг 2013 в 20:49
26
Помимо более лаконичного, это более быстрое решение. Доступ к просмотрам INFORMATION_SCHEMA или sys.columns попадает на диск, в то время как COL_LENGTH использует кэшированные метаданные базы данных.
 – 
wqw
13 Янв 2014 в 12:49
9
Вероятно, это не самый высоко оцененный ответ, потому что он был дан на 2,5 года позже другого. Вот почему я всегда сверяю даты, сравнивая оценки по двум ответам. Чтобы преодолеть ответ, который был дан намного раньше, требуется гораздо больше времени. ;)
 – 
Sean
28 Фев 2014 в 23:35

Измените нижеприведенное в соответствии с вашими конкретными требованиями:

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

Редактировать, чтобы иметь дело с редактированием вопроса : это должно сработать - внимательно просмотрите свой код на предмет глупых ошибок; Вы запрашиваете INFORMATION_SCHEMA в той же базе данных, что и ваша вставка, например? Есть ли у вас опечатка в названии вашей таблицы / столбца в любом из утверждений?

154
Luke Bennett 31 Дек 2014 в 11:57
5
Я только что узнал, что добавление TABLE_SCHEMA = 'mySchema' после предложения where решает проблему.
 – 
Maciej
25 Сен 2008 в 21:01
13
-1: не отвечает на вопрос OP, только добавляет новую информацию о том, как добавить новый столбец, несмотря на то, что OP не спрашивает об этом вообще, не обращается к комментарию OP.
 – 
ANeves thinks SE is evil
2 Ноя 2011 в 15:46
2
+1 Прекрасно отвечает на вопрос OP с бонусом в виде дополнительной информации, которую OP собирался получить в любом случае. И это было то, что я искал.
 – 
Bitterblue
11 Ноя 2019 в 14:07

Попробуй это...

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
77
Soner Gönül 14 Ноя 2011 в 11:18
6
Этот метод также работает с SQL CE, тогда как некоторые другие упомянутые методы - нет.
 – 
SWalters
15 Ноя 2013 в 00:00
9
Вы можете использовать SELECT 1 вместо SELECT TOP 1 1;).
 – 
shA.t
15 Июн 2015 в 15:22
5
В операторе EXISTS SQL автоматически оптимизирует столбцы (так же, как count(*)), так что SELECT * будет достаточно.
 – 
Marc L.
1 Мар 2016 в 22:49
Для полноты картины вам следует рассмотреть возможность добавления and [TABLE_SCHEMA] = '???' в предложение WHERE.
 – 
Andrew Jens
6 Ноя 2019 в 03:03

Для людей, которые проверяют наличие столбца перед тем, как его выбросить.

Начиная с SQL Server 2016 , вы можете использовать новые операторы DIE вместо больших IF оболочек.

ALTER TABLE Table_name DROP COLUMN IF EXISTS Column_name
58
Abel 18 Фев 2021 в 18:15

Вы можете использовать системные представления информационной схемы, чтобы узнать практически все о таблицах, которые вас интересуют:

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

Вы также можете запрашивать представления, хранимые процедуры и многое другое о базе данных, используя представления Information_schema.

43
anonymous 25 Сен 2008 в 16:38
Это именно то, что используется в анкете, ему нужно было знать, как добавить столбец, если он не существует.
 – 
Birel
12 Мар 2020 в 16:46

Попробуйте что-нибудь вроде:

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

Затем используйте это так:

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

Он должен работать как на SQL Server 2000, так и на SQL Server 2005. Не уверен в SQL Server 2008, но не понимаю, почему.

36
shA.t 15 Июн 2015 в 15:27

Сначала проверьте, существует ли комбинация table / column (id / name) в dbo.syscolumns (внутренней таблице SQL Server, содержащей определения полей), и если не выдавать соответствующий запрос ALTER TABLE для его добавления. Например:

IF NOT EXISTS ( SELECT  *
            FROM    syscolumns
            WHERE   id = OBJECT_ID('Client')
                    AND name = 'Name' ) 
ALTER TABLE Client
ADD Name VARCHAR(64) NULL
34
shA.t 15 Июн 2015 в 15:29

Мой хороший друг и коллега показал мне, как можно также использовать блок IF с функциями SQL OBJECT_ID и COLUMNPROPERTY в SQL SERVER 2005+ для проверки наличия столбца. Вы можете использовать что-то похожее на следующее:

Вы можете сами убедиться здесь

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
28
brazilianldsjaguar 21 Мар 2013 в 21:27
1
И, конечно, если вы уверены, что таблица существует, вы можете опустить первую часть условия и проверить только COLUMNPROPERTY.
 – 
Ruud Helderman
12 Дек 2014 в 15:52
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
27
Tuomo Kämäräinen 3 Мар 2011 в 18:49

Это сработало для меня в SQL 2000:

IF EXISTS 
(
    SELECT * 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE table_name = 'table_name' 
    AND column_name = 'column_name'
)
BEGIN
...
END
23
Joe M 23 Мар 2017 в 22:31

Попробуй это

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') 
22
Pரதீப் 21 Дек 2014 в 17:35
Вам не нужен INFORMATION_SCHEMA.TABLES, и вы не фильтруете столбцы для определенной таблицы, поэтому иногда он возвращает более одной строки для тех же имен столбцов в отдельных таблицах;).
 – 
shA.t
15 Июн 2015 в 15:34

Мне нужно было подобное для SQL SERVER 2000, и, как указывает @Mitch, это работает только в 2005+.

Если это поможет кому-то еще, вот что в итоге сработало для меня:

if exists (
    select * 
    from 
        sysobjects, syscolumns 
    where 
        sysobjects.id = syscolumns.id 
        and sysobjects.name = 'table' 
        and syscolumns.name = 'column')
19
SuicideSheep 16 Мар 2017 в 10:30
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
15
Dale K 7 Мар 2019 в 09:06
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;
14
DeanOC 17 Сен 2019 в 04:40
2
Я думаю, вы имели в виду table_schema = 'schema_name'.
 – 
Tab Alleman
28 Июл 2014 в 17:17

Версия временной таблицы принятого ответа:

if (exists(select 1 
             from tempdb.sys.columns  
            where Name = 'columnName'
              and Object_ID = object_id('tempdb..#tableName')))
begin
...
end
11
Community 23 Май 2017 в 14:55
1
Чем это отличается от принятого ответа? Будет ли временная таблица не работать в принятом ответе?
 – 
John Saunders
8 Янв 2015 в 04:24
1
Верный. Принятый ответ не работает для временных таблиц, потому что 'sys.columns' должен быть указан как 'tempdb.sys.columns', а имени таблицы должно предшествовать 'tempdb ..'.
 – 
crokusek
8 Янв 2015 в 23:08
select distinct object_name(sc.id)
from syscolumns sc,sysobjects so  
where sc.name like '%col_name%' and so.type='U'
10
Uwe Keim 6 Дек 2013 в 19:27

Проверить наличие столбца можно несколькими способами. Я настоятельно рекомендую использовать INFORMATION_SCHEMA.COLUMNS, поскольку он создан для общения с пользователем. Рассмотрим следующие таблицы:

 sys.objects
 sys.columns

И даже некоторые другие методы доступа, доступные для проверки system catalog.

Кроме того, нет необходимости использовать SELECT *, просто проверьте его с помощью NULL value

IF EXISTS(
           SELECT NULL 
           FROM INFORMATION_SCHEMA.COLUMNS
           WHERE
             TABLE_NAME = 'myTableName'
             AND COLUMN_NAME = 'myColumnName'
         ) 
8
Ali Elmi 28 Апр 2018 в 17:23
1
Независимо от того, даже если вы SELECT * с EXISTS, потому что, когда существует, он на самом деле не выбирает все строки и все столбцы, внутренне он просто проверяет наличие, а не фактически проверяет все строки и колонны
 – 
Pawan Nogariya
23 Ноя 2018 в 11:55

Одно из самых простых и понятных решений:

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
7
Arsman Ahmad 24 Май 2017 в 10:17

Вот простой скрипт, который я использую для управления добавлением столбцов в базе данных:

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

В этом примере Name - это ColumnName, который нужно добавить, а Object_Id - это TableName

7
Brien Foss 28 Янв 2018 в 07:41

Сделайте что-нибудь, если столбец не существует:

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

Сделайте что-нибудь, если столбец существует:

BEGIN
    IF (COL_LENGTH('[dbo].[Table]', 'Column ') IS NOT NULL)
    BEGIN
        //Do something
    END
END;
5
Jagjit Singh 1 Ноя 2019 в 14:53

Нижеприведенный запрос можно использовать, чтобы проверить, существует ли в таблице искомый столбец. Мы можем принять решение на основе результатов поиска, как показано ниже.

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
4
Suraj Kumar 30 Окт 2018 в 17:31

Еще одна вариация ...

SELECT 
  Count(*) AS existFlag 
FROM 
  sys.columns 
WHERE 
  [name] = N 'ColumnName' 
  AND [object_id] = OBJECT_ID(N 'TableName')
3
Bikramjeet Singh 7 Мар 2019 в 09:05

Другой вклад - это следующий пример, в котором столбец добавляется, если он не существует.

    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

Надеюсь, поможет. Симона

3
Simone Spagna 12 Июл 2019 в 02:18
//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
3
comfortchambeshi 11 Авг 2020 в 21:51

Таблица -> таблица скриптов как -> новые окна - у вас есть дизайн-скрипт. проверьте и найдите имя столбца в новых окнах

1
arnav 10 Май 2019 в 18:56

Выполните приведенный ниже запрос, чтобы проверить, существует ли столбец в данной таблице:

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';
1
S Krishna 29 Май 2019 в 16:43

Я бы предпочел INFORMATION_SCHEMA.COLUMNS системной таблице, потому что Microsoft не гарантирует сохранение системных таблиц между версиями. Например, dbo.syscolumns все еще работает в SQL 2008, но он устарел и может быть удален в любое время в будущем.

49
Christian Hayter 26 Июн 2009 в 12:58
7
Ну да, это само собой разумеется, поскольку представления INFORMATION_SCHEMA содержат только метаданные стандарта ANSI. Однако этого достаточно для проверки существования.
 – 
Christian Hayter
26 Фев 2013 в 21:15
4
Microsoft заявляет: «В будущих выпусках SQL Server Microsoft может расширить определение любого представления системного каталога, добавив столбцы в конец списка столбцов. Мы не рекомендуем использовать синтаксис SELECT * FROM sys.catalog_view_name в производственном коде, поскольку количество возвращенные столбцы могут измениться и нарушить работу вашего приложения ". Это означает, что они не будут удалять столбцы или изменять их порядок. Этого достаточно для обратной совместимости, кроме крайних случаев.
 – 
siride
13 Июл 2013 в 01:26
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
Mohamad Reza Shahrestani 8 Июл 2019 в 13:58

Ответ Пшеницы хорош, но предполагается, что у вас нет одинаковых пар имени таблицы / имени столбца в какой-либо схеме или базе данных. Чтобы сделать его безопасным для этого состояния, используйте это ...

select *
from Information_Schema.Columns
where Table_Catalog = 'DatabaseName'
  and Table_Schema = 'SchemaName'
  and Table_Name = 'TableName'
  and Column_Name = 'ColumnName'
8
Daniel Barbalace 26 Мар 2015 в 20:42