Добавить столбец в таблицу, если он еще не существует

188

Я хочу написать запрос для MS SQL Server, который добавляет столбец в таблицу. Но я не хочу отображать ошибки, когда запускаю / выполняю следующий запрос.

Я использую этот вид запроса, чтобы добавить таблицу ...

IF EXISTS (
       SELECT *
       FROM   sys.objects
       WHERE  OBJECT_ID = OBJECT_ID(N'[dbo].[Person]')
              AND TYPE IN (N'U')
   )

Но я не знаю, как написать этот запрос для столбца.

Tavousi
источник
Вы должны использовать sys.tablesвместо «универсальный» sys.objects- тогда вам не нужно явно указывать тип (это очевидно из sys.tablesуже ....)
marc_s
COL_LENGTH Alternative работает только с SQL-Server 2008, но работает.
Пол-Анри

Ответы:

219

Вы можете использовать аналогичную конструкцию, используя sys.columnsтаблицу io sys.objects.

IF NOT EXISTS (
  SELECT * 
  FROM   sys.columns 
  WHERE  object_id = OBJECT_ID(N'[dbo].[Person]') 
         AND name = 'ColumnName'
)
Ливен Керсмакерс
источник
42
Обратите внимание, что в этом случае вы хотите использовать IF NOT EXISTS в вашем реальном коде.
Nat
2
Для оптимизированного запроса вы можете использовать топ 1 с оператором выбора
Banketeshvar Narayan
11
@BanketeshvarNarayan это неправильно. Планы выполнения подзапросов в EXISTSпредложении идентичны. Такие вещи, как SELECT 1или SELECT TOP 1не нужны. Само EXISTSпредложение указывает оптимизатору запросов выполнять только минимальные чтения, необходимые для оценки EXISTS... хотя бы в SQL Server. Другие механизмы БД могут иметь более или менее эффективный оптимизатор запросов.
Кеннет Кохран
9
@BanketeshvarNarayan Если вы оптимизируете свои ADD Columnзапросы ... вы должны запускать их слишком часто!
Фентон
1
@ user391339 - Я опубликовал конструкцию, аналогичную опубликованной OP, но да, если вы хотите предпринять действия, если столбец не существует, оператор будет ЕСЛИ НЕ СУЩЕСТВУЕТ. Я действительно не чувствую необходимости редактировать ответ для этого, но не стесняйтесь редактировать себя, если вы думаете, что это улучшение.
Ливен Керсмакерс
91
IF COL_LENGTH('table_name', 'column_name') IS NULL
BEGIN
    ALTER TABLE table_name
    ADD [column_name] INT
END
SPL
источник
1
Я попытался сделать это, но он возвращает ошибку, которая утверждает, что функция COL_LENGTH не существует.
ThEpRoGrAmMiNgNoOb
3
Требуется SQL Server 2008+
Роберт Браун
6
Небольшое дополнение - не следует использовать квадратные скобки в имени столбца, так как COL_LENGTH('table_name', '[column_name]')в SQL Server 2016 всегда возвращаются пустые значения ( COL_LENGTH('[table_name]', 'column_name') works as expected).
остановочный кран
33

Еще одна альтернатива. Я предпочитаю такой подход, потому что он меньше пишет, но оба выполняют одно и то же.

IF COLUMNPROPERTY(OBJECT_ID('dbo.Person'), 'ColumnName', 'ColumnId') IS NULL
BEGIN
    ALTER TABLE Person 
    ADD ColumnName VARCHAR(MAX) NOT NULL
END

Я также заметил, что ваш ищет, где таблица существует, очевидно, именно это

 if COLUMNPROPERTY( OBJECT_ID('dbo.Person'),'ColumnName','ColumnId') is not null
JStead
источник
2
Мне это нравится. Я думаю, что лучшая часть публикации здесь - это поиск драгоценных камней, подобных этому.
JStead
2
Что такое «ColumnId»?
Мариус
ColumnId - это имя свойства столбца, с которым вы проверяете. Возможно, вы могли использовать любое имя свойства, которое существует в столбце, например имя и т. Д.
Жак Бош,
5

Вот еще один вариант, который работал для меня.

IF NOT EXISTS (SELECT 1
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE upper(TABLE_NAME) = 'TABLENAME'
        AND upper(COLUMN_NAME) = 'COLUMNNAME')
BEGIN
    ALTER TABLE [dbo].[Person] ADD Column
END
GO

РЕДАКТИРОВАТЬ: Обратите внимание, что INFORMATION_SCHEMAпредставления не всегда могут быть обновлены, SYS.COLUMNSвместо этого используйте :

IF NOT EXISTS (SELECT 1 FROM SYS.COLUMNS....

Адиль Х. Раза
источник
0
IF NOT EXISTS (SELECT * FROM syscolumns
  WHERE ID=OBJECT_ID('[db].[Employee]') AND NAME='EmpName')
  ALTER TABLE [db].[Employee]
  ADD [EmpName] VARCHAR(10)
GO

Надеюсь, это поможет. Больше информации

ShaileshDev
источник
У меня это работало на SqlServer 2000, а принятый ответ - нет. Представления sys. *, Кажется, были добавлены где-то около SqlServer 2005, ср. docs.microsoft.com/en-us/sql/relational-databases/…
ZeRemz
0

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

IF NOT EXISTS (
  SELECT * 
  FROM   DatabaseName.sys.columns 
  WHERE  object_id = OBJECT_ID(N'[DatabaseName].[dbo].[TableName]') 
         AND name = 'ColumnName'
)
Ezra
источник
-1
IF NOT EXISTS (SELECT 1  FROM SYS.COLUMNS WHERE  
OBJECT_ID = OBJECT_ID(N'[dbo].[Person]') AND name = 'DateOfBirth')
BEGIN
ALTER TABLE [dbo].[Person] ADD DateOfBirth DATETIME
END
Код первый
источник