ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

我实际上并不认为问题中的代码有任何问题:在 2008 R2 中对我来说效果很好。 (也许您在错误的数据库中运行它?也许您的数据库区分大小写,而您的 myTableName / myColumnName 字符串中的大小写不正确?这种类型的查询似乎比 COL_LENGTH 解决方案更灵活:我可以通过适当地为“INFORMATION_SCHEMA”添加前缀来针对不同的数据库甚至通过数据库链接运行它。无法使用 COL_LENGTH 元数据函数来执行此操作。
@mwardm - COL_LENGTH('AdventureWorks2012.HumanResources.Department ','ModifiedDate') 工作正常。
相关的小提示:如果您想在添加列后立即更新列(我相信很多用户都在为此目的搜索这篇文章),您可以使用 EXEC sp_executesql 和形成的 UPDATE 语句。
真正的答案是您应该添加要检查的数据库,因此它是 FROM [YourDatabase].INFORMATION_SCHEMA.COLUMNS
您还可以非常简单地使用 syscolumns 和 sysobjects。

M
Mitch Wheat

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
@HemendraSinghChauhan - 那是因为它们不是名字的一部分。与 sys.columns 中的名称进行比较时,您还会发现
当字段 id varchar(max) = null 时,较短的版本不起作用
@AlejandroDG 你能举个例子吗?我会说,这种说法是不正确的。
@sur - 那么在什么意义上这意味着“AlejandroDG 是对的”?谓词是 IS NOT NULL 而不是 >0
P
Peter Mortensen

更简洁的版本

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


这比其他一些答案可读性差,这可能是为什么它的评价不高。
@Bill - 以什么方式不那么可读?在 Firefox 中看起来不错。这个答案比接受的答案晚了 2 年多,这解释了 IMO 的评级。如果您的意思不太清楚它是否存在,请检查这种类型的习语在 SQL Server 中很常见。例如,使用 IF OBJECT_ID('TableName','U') IS NULL 检查对象是否存在或使用 DB_ID('foo') 检查数据库是否存在。
@MartinSmith 我敢肯定他的意思是可读性较差,因为如果您不知道这个习语,并且您从其他人那里继承了此代码,那么您将不会立即理解代码的作用。有点像用 C++ 编写 x>>2 而不是 x/4。更冗长的代码 (if exists (select column_name from information_schema ...)) 占用更多空间,但没有人会挠头试图弄清楚它的作用。
除了更简洁之外,这是一种更快的解决方案。访问 INFORMATION_SCHEMA 视图或 sys.columns 会命中磁盘,而 COL_LENGTH 使用缓存的数据库元数据。
这可能不是评价最高的答案,因为它是在另一个答案之后 2.5 年给出的。这就是为什么我在比较两个答案的评分时总是检查日期。克服更早给出的答案需要更长的时间。 ;)
P
Peter Mortensen

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

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


我刚刚发现在 where 子句之后添加 TABLE_SCHEMA = 'mySchema' 可以解决问题。
-1:不回答 OP 的问题,只添加有关如何添加新列的新信息,尽管 OP 根本没有询问这一点,也没有解决 OP 的评论。
+1 完美地回答了 OP 的问题,并获得了 OP 下一步想要获得的额外信息。这就是我一直在寻找的。
S
Soner Gönül

尝试这个...

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

此方法也适用于 SQL CE,而提到的其他一些方法则不适用。
您可以使用 SELECT 1 代替 SELECT TOP 1 1 ;)。
EXISTS 语句中,SQL 会自动优化列(很像 count(*)),因此 SELECT * 就足够了。
为了完整起见,您应该考虑将 and [TABLE_SCHEMA] = '???' 添加到 WHERE 子句中。
M
Martin Smith

对于在删除列之前检查列存在的人。

SQL Server 2016 开始,您可以使用新的 DIE (Drop If Exists) 语句代替大型 IF 包装器

ALTER TABLE Table_name DROP COLUMN IF EXISTS Column_name

但是那里没有“DIE”(?)。解释是什么?最好通过更改答案来澄清它,而不是在评论中(但没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的)。独立的,你能链接到文档吗?
P
Peter Mortensen

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


是的,这是不言而喻的,因为 INFORMATION_SCHEMA 视图仅包含 ANSI 标准元数据。但是,这对于存在测试来说已经足够了。
微软表示“在 SQL Server 的未来版本中,微软可能会通过在列列表的末尾添加列来扩充任何系统目录视图的定义。我们建议不要在生产代码中使用语法 SELECT * FROM sys.catalog_view_name,因为返回的列可能会改变并破坏您的应用程序。”这意味着他们不会删除列或更改其顺序。对于除边缘情况之外的所有情况,这已经足够向后兼容了。
a
anonymous

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

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

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


这正是问卷所使用的,他需要知道如果该列不存在,如何添加该列。
P
Peter Mortensen

尝试类似:

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 2000SQL Server 2005。我不确定 SQL Server 2008,但我不明白为什么不这样做。


s
shA.t

首先检查 dbo.syscolumns(包含字段定义的内部 SQL Server 表)中是否存在 table/column(id/name) 组合,如果不存在,则发出适当的 ALTER TABLE 查询以添加它。例如:

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

P
Peter Mortensen

我的一位好朋友和同事向我展示了如何在 SQL Server 2005 中使用带有 SQL 函数 OBJECT_IDCOLUMNPROPERTYIF 块以及稍后检查列。您可以使用类似于以下内容的内容:

You can see for yourself here

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

当然,如果您确信该表存在,您可以省略条件的第一部分并仅检查 COLUMNPROPERTY
T
Tuomo Kämäräinen
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

一个解释将是有序的。例如,想法/要点是什么?来自 the Help Center“...总是解释为什么你提出的解决方案是合适的以及它是如何工作的”。请通过 editing (changing) your answer 回复,而不是在评论中(没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的)。
P
Peter Mortensen

这在 SQL Server 2000 中对我有用:

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

P
Pரதீப்

尝试这个

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 并且您不过滤特定表的列,因此它有时会为单独的表中的相同列名返回多行;)。
P
Peter Mortensen

对于 SQL Server 2000,我需要类似的东西,并且作为 Mitch points out,这仅适用于 SQL Server 2005 或更高版本。

这最终对我有用:

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

P
Peter Mortensen
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;

我认为您的意思是 table_schema='schema_name'。
D
Dale K
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

P
Peter Mortensen

accepted answer 的临时表版本:

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

这与接受的答案有什么不同?临时表在接受的答案中不起作用吗?
正确的。接受的答案不适用于临时表,因为“sys.columns”必须指定为“tempdb.sys.columns”,并且表名必须以“tempdb..”开头。
P
Peter Mortensen

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

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

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

A
Ali Elmi

有几种方法可以检查列的存在。我强烈建议使用 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'
         ) 

即使您使用 SELECT *EXISTS,因为当使用 exists 时,它并不会真正选择所有行和所有列,在内部它只是检查是否存在,而不是实际检查所有行和列
P
Peter Mortensen

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

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

应该是这样的。有了解释,而不仅仅是“试试这个”的答案。
P
Peter Mortensen

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

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;

为什么“列”后面有空格?
B
Brien Foss

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

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 是要添加的 ColumnNameObject_IdTableName


P
Peter Mortensen

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

    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

P
Peter Mortensen

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

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

B
Bikramjeet Singh

还有一个变种...

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

变种什么?另一个答案? Mike Wheat's?还是独立的?
一个解释将是有序的。例如,想法/要点是什么?与之前的答案有何不同?它在什么(版本等)上进行了测试?来自 the Help Center“...总是解释为什么你提出的解决方案是合适的以及它是如何工作的”。请通过 editing (changing) your answer 回复,而不是在评论中(没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的)。
P
Peter Mortensen

您可以一次检查 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];

S
S Krishna

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

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

P
Peter Mortensen
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

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

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