如何检查 SQL Server 表中是否存在列

How to check if a column exists in a SQL Server table

提问人:Maciej 提问时间:9/25/2008 最后编辑:Peter MortensenMaciej 更新时间:3/7/2023 访问量:1617835

问:

如果不存在,我需要添加一个特定的列。我有类似以下内容的东西,但它总是返回 false:

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

如何检查SQL Server数据库的表中是否存在列?

SQL-服务器-2008 T-SQL SQL 服务器-2016

评论

18赞 mwardm 6/13/2013
我实际上并不认为问题中的代码有什么问题:在 2008 R2 中对我来说效果很好。(也许您在错误的数据库中运行它?也许您的数据库区分大小写,并且您的 myTableName / myColumnName 字符串中没有大小写?这种类型的查询似乎比COL_LENGTH解决方案更灵活:我能够针对不同的数据库运行它,甚至通过适当的前缀“INFORMATION_SCHEMA”来运行它。无法看到如何使用COL_LENGTH元数据函数执行此操作。
4赞 Martin Smith 9/13/2013
@mwardm - 工作正常。COL_LENGTH('AdventureWorks2012.HumanResources.Department ','ModifiedDate')
7赞 cassandrad 4/16/2015
一些相关的提示:如果你想在添加列后立即更新一列(我相信很多用户都在为此目的搜索这篇文章),你可以使用formed statement。EXEC sp_executesqlUPDATE
2赞 Alex Kwitny 6/26/2015
真正的答案是你应该添加你正在检查的数据库,所以它是FROM [YourDatabase].INFORMATION_SCHEMA.COLUMNS
1赞 dcpking 8/29/2020
您还可以非常简单地使用 syscolumns 和 sysobjects。

答:

89赞 Leon Tayson 9/25/2008 #1

试试这个...

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

评论

6赞 SWalters 11/15/2013
此方法也适用于 SQL CE,而提到的其他一些方法则不适用。
9赞 shA.t 6/15/2015
您可以使用代替;)。SELECT 1SELECT TOP 1 1
6赞 Marc L. 3/2/2016
在语句中,SQL会自动优化列(很像),所以就足够了。EXISTScount(*)SELECT *
4赞 Andrew Jens 11/6/2019
为了完整起见,您应该考虑添加 WHERE 子句。and [TABLE_SCHEMA] = '???'
178赞 Luke Bennett 9/25/2008 #2

调整以下内容以满足您的特定要求:

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?您在任一语句中的表/列名称中是否有拼写错误?

评论

6赞 Maciej 9/26/2008
我刚刚发现在where子句之后添加TABLE_SCHEMA = 'mySchema'可以解决问题。
13赞 ANeves 11/2/2011
-1:不回答 OP 的问题,只添加了有关如何添加新 collumn 的新信息,尽管 OP 根本没有询问这一点,也没有解决 OP 的评论。
4赞 Bitterblue 11/11/2019
+1 完美地回答了 OP 的问题,并附带了 OP 接下来要获取的额外信息。这就是我一直在寻找的。
0赞 ANeves 12/7/2023
我的意思是,这个答案对我来说没有用,因为我看不出这个问题和问题之间的显着差异。更改为 ,更改为 ,并用 添加 then 分支 ,这些似乎都不重要。如果答案中还有其他遗漏的地方,也许可以明确写下具体的差异/建议?HTH型if existsif not exists*column_namealter table …
34赞 mdb 9/25/2008 #3

首先检查(包含字段定义的内部 SQL Server 表)中是否存在 /(/) 组合,如果没有,则发出相应的查询来添加它。例如:tablecolumnidnamedbo.syscolumnsALTER TABLE

IF NOT EXISTS ( SELECT  *
            FROM    syscolumns
            WHERE   id = OBJECT_ID('Client')
                    AND name = 'Name' ) 
ALTER TABLE Client
ADD Name VARCHAR(64) NULL
44赞 anonymous #4

您可以使用信息架构系统视图来查找有关您感兴趣的表的几乎所有内容:

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

您还可以使用Information_schema视图查询视图、存储过程以及有关数据库的几乎所有内容。

评论

0赞 Attie Wagner 3/12/2020
这正是调查问卷所使用的,如果该列不存在,他需要知道如何添加该列。
35赞 Matt Lacey 9/25/2008 #5

尝试如下操作:

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,但我不明白为什么不。

2354赞 Mitch Wheat 9/25/2008 #6

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

马丁·史密斯(Martin Smith)的版本更短:

IF COL_LENGTH('schemaName.tableName', 'columnName') IS NOT NULL
BEGIN
    -- Column Exists
END

评论

2赞 Hemendra 6/24/2019
在 Martin Smith 的版本中,要提到的一件事是不要在方括号 [ ] 中包含 columnName。当 columnName 位于方括号 [ ] 内时,即使表中存在该列,它也会给出 null
0赞 Martin Smith 6/24/2019
@HemendraSinghChauhan - 那是因为它们不是名称的一部分。您还会发现,当与sys.columns
0赞 Hemendra 6/24/2019
@MartinSmith不知道,我正在使用你的答案并遇到了这个。通常我在添加列时使用方括号,所以我也在函数中使用COL_LENGTH括号。我的代码是这样的:Alter table Table_Name Add [ColumnName] NVarchar(max) NULL; Select COL_LENGTH('[TABLE_NAME]', '[COLUMN_NAME]')
3赞 kapsiR 3/9/2021
@AlejandroDG 您能举个例子吗?我想说,这种说法是不正确的。
4赞 Martin Smith 4/23/2022
@sur - 那么,在什么意义上,这意味着“亚历杭德罗DG是对的”?谓语不是IS NOT NULL>0
50赞 Christian Hayter 6/26/2009 #7

我更喜欢系统表,因为 Microsoft 不保证在版本之间保留系统表。例如,在 SQL Server 2008 中仍然有效,但它已被弃用,将来可以随时删除。INFORMATION_SCHEMA.COLUMNSdbo.syscolumns

评论

7赞 Christian Hayter 2/27/2013
嗯,是的,这是不言而喻的,因为视图只包含 ANSI 标准的元数据。但是,这对于存在性测试来说已经足够了。INFORMATION_SCHEMA
4赞 siride 7/13/2013
Microsoft说:“在SQL Server的未来版本中,Microsoft可以通过在列列表的末尾添加列来扩充任何系统目录视图的定义。我们建议不要在生产代码中使用语法 SELECT * FROM sys.catalog_view_name,因为返回的列数可能会更改并破坏您的应用程序。这意味着他们不会删除列或更改其顺序。对于除边缘情况之外的所有情况,这都足够向后兼容。
26赞 Tuomo Kämäräinen 3/3/2011 #8
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

评论

0赞 Peter Mortensen 4/21/2022
解释是有序的。例如,想法/要点是什么?从帮助中心:“......始终解释为什么您提出的解决方案是合适的,以及它是如何工作的”。请通过编辑(更改)您的答案来回复,而不是在评论中(没有“编辑:”,“更新:”或类似内容 - 答案应该看起来像今天写的一样)。
1147赞 Martin Smith 3/20/2011 #9

更简洁的版本

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

评论

15赞 Bill Yang 12/1/2011
这比其他一些答案的可读性较差,这可能是为什么它的评价不那么高的原因。
45赞 Martin Smith 12/1/2011
@Bill - 以何种方式降低可读性?在Firefox中看起来不错。这个答案比公认的答案晚了 2 年多,这解释了 IMO 的评级。如果你的意思不太清楚它是否存在,请检查这种类型的习语在 SQL Server 中很常见。例如,用于检查对象是否存在或检查数据库是否存在。IF OBJECT_ID('TableName','U') IS NULLDB_ID('foo')
71赞 Kip 8/21/2013
@MartinSmith我敢肯定他的意思是可读性较差,因为如果你不知道这个成语,并且你从别人那里继承了这段代码,你就不会立即理解这段代码的作用。有点像写作而不是用 C++ 编写。更冗长的代码 () 占用了更多的空间,但没有人会挠头试图弄清楚它的作用。x>>2x/4if exists (select column_name from information_schema ...)
28赞 wqw 1/13/2014
除了更简洁之外,这是一种更快的解决方案。访问视图或命中磁盘,同时使用缓存的数据库元数据。INFORMATION_SCHEMAsys.columnsCOL_LENGTH
11赞 Sean 3/1/2014
这可能不是评价最高的答案,因为它是在另一个答案之后 2.5 年给出的。这就是为什么在比较两个答案的评分时,我总是检查日期。克服更早给出的答案需要更长的时间。;)
24赞 Joe M 8/3/2011 #10

这在 SQL Server 2000 中对我有用:

IF EXISTS
(
    SELECT *
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE table_name = 'table_name'
    AND column_name = 'column_name'
)
BEGIN
...
END
21赞 Douglas Tondo 9/30/2011 #11

试试这个

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') 

评论

0赞 shA.t 6/15/2015
您不需要也不需要筛选特定表的列,因此它有时会在单独的表;)中为相同的列名返回多行。INFORMATION_SCHEMA.TABLES
18赞 FrostbiteXIII 5/4/2012 #12

我需要 SQL Server 2000 的类似功能,正如 Mitch 指出的那样,这仅适用于 SQL Server 2005 或更高版本。

这就是最终对我有用的东西:

if exists (
    select *
    from
        sysobjects, syscolumns
    where
        sysobjects.id = syscolumns.id
        and sysobjects.name = 'table'
        and syscolumns.name = 'column')
29赞 brazilianldsjaguar 3/21/2013 #13

我的一位好朋友和同事向我展示了如何在 SQL 函数中使用块,并在 SQL Server 2005 及更高版本中检查列。您可以使用类似于以下内容的内容:IFOBJECT_IDCOLUMNPROPERTY

您可以在这里亲眼看到

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

评论

1赞 Ruud Helderman 12/12/2014
当然,如果您确信该表存在,则可以省略条件的第一部分,仅进行检查。COLUMNPROPERTY
9赞 Nishad 5/23/2013 #14
select distinct object_name(sc.id)
from syscolumns sc,sysobjects so  
where sc.name like '%col_name%' and so.type='U'
16赞 Na30m 9/12/2013 #15
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;

评论

2赞 Tab Alleman 7/28/2014
我想你的意思是 table_schema='schema_name'。
14赞 BYRAKUR SURESH BABU 5/8/2014 #16
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
2赞 Manuel Alves 7/10/2014 #17

又一个变化......

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

评论

0赞 Peter Mortensen 4/21/2022
什么变化?另一个答案?迈克·惠特(Mike Wheat)的?还是独立?
0赞 Peter Mortensen 4/21/2022
解释是有序的。例如,想法/要点是什么?它与之前的答案有何不同?它测试了什么(版本等)?从帮助中心:“......始终解释为什么您提出的解决方案是合适的,以及它是如何工作的”。请通过编辑(更改)您的答案来回复,而不是在评论中(没有“编辑:”,“更新:”或类似内容 - 答案应该看起来像今天写的一样)。
10赞 crokusek 1/8/2015 #18

已接受答案的临时表版本:

if (exists(select 1
           from tempdb.sys.columns
           where Name = 'columnName'
                 and Object_ID = object_id('tempdb..#tableName')))
begin
...
end

评论

2赞 John Saunders 1/8/2015
这与公认的答案有何不同?临时表在公认的答案中不起作用吗?
1赞 crokusek 1/9/2015
正确。接受的答案不适用于临时表,因为“sys.columns”必须指定为“tempdb.sys.columns”,并且表名前面必须有“tempdb..”。
9赞 Daniel Barbalace 3/27/2015 #19

Wheat 的答案很好,但它假设您在任何架构或数据库中都没有任何相同的表名/列名对。为了使这种情况安全,请使用此...

select *
from Information_Schema.Columns
where Table_Catalog = 'DatabaseName'
  and Table_Schema = 'SchemaName'
  and Table_Name = 'TableName'
  and Column_Name = 'ColumnName'

评论

0赞 Peter Mortensen 4/21/2022
这就是它应该的样子。有一个解释,而不仅仅是一个“试试这个”的答案。
9赞 Ali Elmi 2/16/2016 #20

有几种方法可以检查列是否存在。 我强烈建议使用它,因为它是为了与用户通信而创建的。 请考虑下表: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'
         ) 

评论

1赞 Pawan Nogariya 11/23/2018
即使你用 ,因为当使用 exists 时,它并没有真正选择所有的行和所有列,在内部它只是检查是否存在,而不是实际检查所有的行和列SELECT *EXISTS
81赞 Pரதீப் 5/1/2016 #21

适用于在删除列之前检查列是否存在的人员。

从 SQL Server 2016SQL Server 2016SQL Server 2016SQL Server 2016SQL Server 2016SQL Server 2016SQL Server 2016SQL Server 2016SQL Server 2016SQL Server 2016SQL Server 2016SQL Server 2016SQL Server 2016SQL Server 2016SQL Server 20IF

ALTER TABLE Table_name DROP COLUMN IF EXISTS Column_name

评论

1赞 Peter Mortensen 4/21/2022
但是那里没有“DIE”(?解释是什么?最好通过更改答案来澄清它,而不是在评论中(但没有“编辑:”,“更新:”或类似内容 - 答案应该看起来像今天写的一样)。独立,你能链接到文档吗?
3赞 FMFF 12/15/2022
是否有可能做相反的事情?喜欢?ALTER TABLE table_name ADD COLUMN IF NOT EXISTS
6赞 UJS 11/16/2016 #22

下面是我用来管理数据库中列添加的简单脚本:

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

在此示例中,是要添加的 并且是NameColumnNameObject_IdTableName

16赞 Arsman Ahmad 5/24/2017 #23

最简单易懂的解决方案之一是:

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
3赞 Suraj Kumar 10/30/2018 #24

以下查询可用于检查表中是否存在搜索到的列。我们可以根据搜索结果做出决定,如下所示。

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
-1赞 Ilangeeran 4/3/2019 #25
IF EXISTS(SELECT 1 FROM sys.columns
      WHERE Name = N'columnName'
      AND Object_ID = Object_ID(N'schemaName.tableName'))

这应该是解决这个问题的相当简单的方法和直接的解决方案。我已经多次将其用于类似的场景。毫无疑问,它就像一个魅力。

-2赞 Dinesh vishe 5/10/2019 #26

表格→脚本表作为→新窗口 - 你有设计脚本。

在新窗口中检查并查找列名称。

0赞 S Krishna 5/29/2019 #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赞 Mohammad Reza Shahrestani 7/8/2019 #28
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
7赞 Simone Spagna 7/12/2019 #29

另一个贡献是以下示例,如果该列不存在,则添加该列。

    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
10赞 Jagjit Singh 11/1/2019 #30

如果该列不存在,请执行以下操作:

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;

评论

1赞 Peter Mortensen 4/21/2022
为什么“列”后面有空格?
2赞 Mostafa Bouzari 11/2/2021 #31

可以一次检查 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];
1赞 Александр Шабунин 3/7/2023 #32

INFORMATION_SCHEMA使用当前数据库,必须首先调用“使用 [MyDatabase]”