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


1853

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

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

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


12
我实际上不认为问题中的代码有什么问题:在2008 R2中对我来说效果很好。(也许您在错误的数据库中运行它?也许您的数据库区分大小写,并且myTableName / myColumnName字符串中的大小写不正确?这种类型的查询似乎比COL_LENGTH解决方案更灵活:我可以通过适当地加上前缀“ INFORMATION_SCHEMA”来针对不同的数据库甚至通过数据库链接运行它。看不到如何使用COL_LENGTH元数据功能来做到这一点
mwardm 2013年

3
@mwardm- COL_LENGTH('AdventureWorks2012.HumanResources.Department ','ModifiedDate')工作正常。
马丁·史密斯

6
几乎没有相关提示:如果您想在添加列之后立即更新列(我相信许多用户为此目的都在搜索本文),则可以将其EXEC sp_executesql与formed UPDATE语句一起使用。
cassandrad 2015年

真正的答案是,您应该添加要检查的数据库,所以它是FROM [YourDatabase].INFORMATION_SCHEMA.COLUMNS
Alex Kwitny 2015年

Answers:


2054

从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

在马丁·史密斯(Martin Smith)的版本中,要提到的一件事是不要在方括号[]中包含columnName。当columnName在方括号[]内时,即使该列存在于表中,该字段也将为null
Hemendra

@HemendraSinghChauhan-这是因为它们不是名称的一部分。您还会发现,与sys.columns
马丁史密斯

@MartinSmith不知道,我正在使用您的答案并发现了这一点。通常,在添加列时会使用方括号,因此我也在COL_LENGTH函数中使用了方括号。我的代码是这样的:Alter table Table_Name Add [ColumnName] NVarchar(max) NULL; Select COL_LENGTH('[TABLE_NAME]', '[COLUMN_NAME]')
Hemendra

是的,那是无效的。COL_LENGTH需要取消引用的参数。从理论上讲,有人可以创建一个确实具有名称[COLUMN_NAME]- 的列,例如CREATE TABLE #T([[COLUMN_NAME]]] INT); SELECT * FROM #T,如果这不是规则,那将是模棱两可的。
马丁·史密斯

987

更简洁的版本

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始终仅返回有关已提交更改的数据,而与有效的隔离级别无关。


11
这比其他一些答案的可读性差,这可能是为什么它的评价不那么高的原因。
比尔·杨

38
@Bill-用什么方式不太可读?在Firefox中看起来不错。该答案比公认的答案晚发布了两年多,这解释了IMO的等级。如果您不太清楚这是一种存在性检查,则这种成语在SQL Server中非常普遍。例如IF OBJECT_ID('TableName','U') IS NULL用于检查对象是否存在或DB_ID('foo')检查数据库是否存在。
马丁·史密斯,

59
@MartinSmith我敢肯定他的意思是可读性较差,因为如果您不了解该成语,并且您从其他人那里继承了此代码,您将不会立即理解该代码的作用。有点像编写x>>2而不是x/4用C ++ 编写。较冗长的代码(if exists (select column_name from information_schema ...))占用了更多空间,但是没有人会摸索试图弄清楚它的作用。
Kip

22
除了更简洁以外,这是一种更快的解决方案。使用缓存的数据库元数据时访问INFORMATION_SCHEMA视图或访问sys.columns磁盘COL_LENGTH
wqw

7
这可能不是获得最高评价的答案,因为它比另一个答案要晚2.5年。这就是为什么我在比较两个答案的等级时总是检查日期。克服早先给出的答案需要花费更长的时间。;)
肖恩

149

调整以下内容以适合您的特定要求:

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?您的表/列名称中是否有错字?


3
我刚刚发现在where子句之后添加TABLE_SCHEMA ='mySchema'可以解决此问题。
Maciej

12
-1:不回答OP的问题,尽管OP根本不询问,但仅添加有关如何添加新列的新信息,不解决OP的评论。
ANeves

1
+1回答OP的问题,再加上OP下一步要去的其他信息,就可以完美地回答该问题。这就是我想要的。
Bitterblue

74

尝试这个...

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
此方法也可用于SQL CE,而其他提到的方法则无效。
突击队-恢复莫妮卡2013年

9
您可以使用SELECT 1代替SELECT TOP 1 1;)。
shA.t 2015年

4
在一条EXISTS语句中,SQL会自动优化掉列(很像count(*)),因此SELECT *就足够了。
Marc L.

为了完整起见,您应该考虑添加and [TABLE_SCHEMA] = '???'WHERE子句。
Andrew Jens

50

对于正在检查该列存在的人员来说,将其删除。

SQL Server 2016中,您可以使用新的DIE语句代替大型IF包装器

ALTER TABLE Table_name DROP COLUMN IF EXISTS Column_name

47

我宁愿选择INFORMATION_SCHEMA.COLUMNS系统表,因为Microsoft不能保证在版本之间保留系统表。例如,dbo.syscolumns在SQL 2008中仍然可以使用,但已过时,以后可以随时删除。



5
好吧,这是不言而喻的,因为INFORMATION_SCHEMA视图仅包含ANSI标准元数据。但是,这对于存在测试是足够的。
Christian Hayter

3
Microsoft说:“在SQL Server的将来版本中,Microsoft可以通过在列列表的末尾添加列来增加任何系统目录视图的定义。我们建议不要在生产代码中使用语法SELECT * FROM sys.catalog_view_name,因为返回的列可能会更改并破坏您的应用程序。” 这意味着他们不会删除列或更改其顺序。对于几乎所有情况,向后兼容性都足够好。
siride

42

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

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

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


这正是问卷使用的方式,他需要知道如何添加该列(如果不存在)。
Birel

35

尝试类似的东西:

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,但看不到为什么。


34

首先检查table/ columnid/ 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

28

一个好朋友和我的同事告诉我如何你也可以使用一个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

1
当然,如果您确信该表存在,则可以省略条件的第一部分并COLUMNPROPERTY仅进行检查。
Ruud Helderman 2014年

26
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

22

这在SQL 2000中对我有用:

IF EXISTS 
(
    SELECT * 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE table_name = 'table_name' 
    AND column_name = 'column_name'
)
BEGIN
...
END

21

尝试这个

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

您不需要,也不需要INFORMATION_SCHEMA.TABLES过滤特定表的列,因此对于单独表中的相同列名,有时它会返回多行;)。
shA.t 2015年

19

我需要类似的SQL SERVER 2000,并且正如@Mitch指出的那样,这仅适用于inm 2005+。

如果它可以帮助其他人,这最终对我有用:

if exists (
    select * 
    from 
        sysobjects, syscolumns 
    where 
        sysobjects.id = syscolumns.id 
        and sysobjects.name = 'table' 
        and syscolumns.name = 'column')

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

13
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
我认为您的意思是table_schema ='schema_name'。
Tab Alleman 2014年

11

接受答案的临时表版本:

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

1
这与接受的答案有何不同?临时表在接受的答案中不起作用吗?
约翰·桑德斯

1
正确。接受的答案不适用于临时表,因为必须将“ sys.columns”指定为“ tempdb.sys.columns”,并且表名必须以“ tempdb ..”开头。
crokusek

10
select distinct object_name(sc.id)
from syscolumns sc,sysobjects so  
where sc.name like '%col_name%' and so.type='U'

8

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

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

8

有几种检查列是否存在的方法。我强烈建议使用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
不管您是否SELECT *使用EXISTS,因为使用时都不会真正选择所有行和所有列,在内部它只是检查是否存在而实际上不检查所有行和列
Pawan Nogariya

7

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

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

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

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

在此示例中,NameColumnName要添加的和Object_IdTableName


4

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

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

table-> script table as-> new windows-您具有设计脚本。检查并在新窗口中找到列名


1

执行以下查询以检查给定表中是否存在该列:

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

另一个贡献是添加了该列(如果不存在)的以下示例。

    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

希望能帮助到你。西蒙妮


0
IF EXISTS(SELECT 1 FROM sys.columns 
      WHERE Name = N'columnName'
      AND Object_ID = Object_ID(N'schemaName.tableName'))

这应该是相当容易的方法,并且可以直接解决该问题。对于类似的情况,我已经多次使用了。毫无疑问,它就像一种魅力。


0
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

0

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

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;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.