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

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

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

2085
Maciej 25 Сен 2008 в 16:34
16
На самом деле я не думаю, что что-то не так с кодом в вопросе: у меня отлично работает в 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

32 ответа

Лучший ответ

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
2279
Mitch Wheat 12 Апр 2017 в 06:35
1
В версии Мартина Смита следует упомянуть одну вещь - не включать имя столбца в квадратные скобки []. Если имя столбца заключено в квадратные скобки [], будет возвращено значение null, даже если столбец существует в таблице.
 – 
Hemendra
24 Июн 2019 в 10:57
- это потому, что они не являются частью имени. Вы также обнаружите, что при сравнении с именем в sys.columns
 – 
Martin Smith
24 Июн 2019 в 10:59
1
Более короткая версия не работает, если идентификатор поля varchar (max) = null
 – 
AlejandroDG
13 Авг 2020 в 20:35
2
Можете ли вы привести пример? Я бы сказал, что это утверждение не соответствует действительности.
 – 
kapsiR
9 Мар 2021 в 18:46
1
- Так в каком смысле это означает «Алехандро ДГ прав»? Предикат IS NOT NULL не >0
 – 
Martin Smith
23 Апр 2022 в 08:23

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

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, всегда возвращают данные только о зафиксированных изменениях, независимо от действующего уровня изоляции.

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

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

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
84
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
6
В операторе EXISTS SQL автоматически оптимизирует столбцы (так же, как count(*)), так что SELECT * будет достаточно.
 – 
Marc L.
1 Мар 2016 в 22:49
2
Для полноты картины вам следует рассмотреть возможность добавления and [TABLE_SCHEMA] = '???' в предложение WHERE.
 – 
Andrew Jens
6 Ноя 2019 в 03:03

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

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

ALTER TABLE Table_name DROP COLUMN IF EXISTS Column_name
72
Martin Smith 23 Апр 2022 в 08:25
Но там нет "УМЕРЕТЬ"(?). Каково объяснение? Желательно уточнить это, изменив ответ, а не здесь, в комментариях (но без «Изменить:», «Обновить:» или аналогичного — ответ должен выглядеть так, как если бы это было написано сегодня). Независимый, можно ссылку на документацию?
 – 
Peter Mortensen
20 Апр 2022 в 23:33

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

49
Peter Mortensen 20 Апр 2022 в 23:14
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

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

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

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

44
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, но не понимаю, почему бы и нет.

35
Peter Mortensen 20 Апр 2022 в 23:13
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
26
Tuomo Kämäräinen 3 Мар 2011 в 18:49
Объяснение было бы в порядке. Например, какова идея/суть? Из Справочного центра: "...всегда объясняйте, почему предлагаемое вами решение подходит и как оно работает" . Пожалуйста, ответьте, отредактировав (изменив) свой ответ, а не здесь, в комментариях (без "Редактировать:", "Обновить:" или подобное — ответ должен выглядеть так, как будто он был написан сегодня).
 – 
Peter Mortensen
20 Апр 2022 в 23:15

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

IF EXISTS
(
    SELECT *
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE table_name = 'table_name'
    AND column_name = 'column_name'
)
BEGIN
...
END
24
Peter Mortensen 20 Апр 2022 в 23:17

Попробуй это

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

Проверить наличие столбца можно несколькими способами. Я настоятельно рекомендую использовать 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'
         ) 
9
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
10
Peter Mortensen 22 Апр 2022 в 10:37

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

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

6
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;
9
Peter Mortensen 20 Апр 2022 в 23:48
1
Почему после "Столбец" пробел?
 – 
Peter Mortensen
20 Апр 2022 в 23:49

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

SELECT 
  Count(*) AS existFlag 
FROM 
  sys.columns 
WHERE 
  [name] = N 'ColumnName' 
  AND [object_id] = OBJECT_ID(N 'TableName')
2
Bikramjeet Singh 7 Мар 2019 в 09:05
Объяснение было бы в порядке. Например, какова идея/суть? Чем он отличается от предыдущих ответов? На чем тестировалось (версии и т.д.)? Из Справочного центра: "...всегда объясняйте, почему предлагаемое вами решение подходит и как оно работает" . Пожалуйста, ответьте, отредактировав (изменив) свой ответ, а не здесь, в комментариях (без "Редактировать:", "Обновить:" или подобное — ответ должен выглядеть так, как будто он был написан сегодня).
 – 
Peter Mortensen
20 Апр 2022 в 23: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 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 exist in table
END
0
Peter Mortensen 20 Апр 2022 в 23:52

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

1
arnav 10 Май 2019 в 18:56

Мой хороший друг и коллега показал мне, как можно использовать блок 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
29
Peter Mortensen 20 Апр 2022 в 23:22
1
И, конечно, если вы уверены, что таблица существует, вы можете опустить первую часть условия и проверить только COLUMNPROPERTY.
 – 
Ruud Helderman
12 Дек 2014 в 15:52

Еще одним вкладом является следующий пример, который добавляет столбец, если он не существует.

    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
6
Peter Mortensen 20 Апр 2022 в 23:46

Вы можете одновременно проверить несколько столбцов в SQLDB и вернуть строку в качестве статуса, чтобы проверить, существуют ли столбцы:

IF EXISTS
        (
          SELECT *
          FROM INFORMATION_SCHEMA.COLUMNS
          WHERE TABLE_NAME = 'Table Name'
          AND(COLUMN_NAME = 'column 1'
          or COLUMN_NAME = 'column 2'
          or COLUMN_NAME = 'column 3'
          or COLUMN_NAME = 'column 4')
        )
        SELECT 'Column exists in table' AS[Status];
        ELSE
        SELECT 'Column does not exist in table' AS[Status];
2
Peter Mortensen 20 Апр 2022 в 23:55
IF EXISTS(SELECT 1 FROM sys.columns
      WHERE Name = N'columnName'
      AND Object_ID = Object_ID(N'schemaName.tableName'))

Это должно быть довольно простым способом и простым решением этой проблемы. Я использовал это несколько раз для подобных сценариев. Он работает как шарм, в этом нет никаких сомнений.

-1
Peter Mortensen 20 Апр 2022 в 23:39

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

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
3
Peter Mortensen 20 Апр 2022 в 23:38
//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
4
comfortchambeshi 11 Авг 2020 в 21:51

Мне нужно было что-то подобное для SQL Server 2000 и, поскольку Митч указывает, это работает только в SQL Server 2005 или более поздней версии.

Вот что у меня сработало в итоге:

if exists (
    select *
    from
        sysobjects, syscolumns
    where
        sysobjects.id = syscolumns.id
        and sysobjects.name = 'table'
        and syscolumns.name = 'column')
18
Peter Mortensen 20 Апр 2022 в 23:20
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
14
Dale K 7 Мар 2019 в 09:06

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

if (exists(select 1
           from tempdb.sys.columns
           where Name = 'columnName'
                 and Object_ID = object_id('tempdb..#tableName')))
begin
...
end
10
Peter Mortensen 22 Апр 2022 в 10:34
2
Чем это отличается от принятого ответа? Будет ли временная таблица не работать в принятом ответе?
 – 
John Saunders
8 Янв 2015 в 04:24
1
Верный. Принятый ответ не работает для временных таблиц, потому что 'sys.columns' должен быть указан как 'tempdb.sys.columns', а имени таблицы должно предшествовать 'tempdb ..'.
 – 
crokusek
8 Янв 2015 в 23:08
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;
16
Peter Mortensen 20 Апр 2022 в 23:25
2
Я думаю, вы имели в виду table_schema = 'schema_name'.
 – 
Tab Alleman
28 Июл 2014 в 17:17
select distinct object_name(sc.id)
from syscolumns sc,sysobjects so  
where sc.name like '%col_name%' and so.type='U'
9
Uwe Keim 6 Дек 2013 в 19:27

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

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

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

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 в той же базе данных, к которой, например, применяется ваша вставка? У вас есть опечатка в имени таблицы/столбца в любом из утверждений?

172
Peter Mortensen 20 Апр 2022 в 23:11
6
Я только что узнал, что добавление TABLE_SCHEMA = 'mySchema' после предложения where решает проблему.
 – 
Maciej
25 Сен 2008 в 21:01
13
-1: не отвечает на вопрос OP, только добавляет новую информацию о том, как добавить новый столбец, несмотря на то, что OP не спрашивает об этом вообще, не обращается к комментарию OP.
 – 
ANeves
2 Ноя 2011 в 15:46
4
+1 Прекрасно отвечает на вопрос OP с бонусом в виде дополнительной информации, которую OP собирался получить в любом случае. И это было то, что я искал.
 – 
Bitterblue
11 Ноя 2019 в 14:07