检查SQL Server中是否存在表

时间:2008-10-03 16:00:34

标签: sql-server tsql sql-server-2005 sql-server-2000

我希望这是关于如何使用SQL语句检查SQL Server 2000/2005中是否存在表的最终讨论。

当谷歌获得答案时,你会得到很多不同的答案。是否有正式/后向和前向兼容的方式?

以下是两种可能的方法。这两者中哪一个是标准/最佳方式?

第一种方式:

IF EXISTS (SELECT 1 
           FROM INFORMATION_SCHEMA.TABLES 
           WHERE TABLE_TYPE='BASE TABLE' 
           AND TABLE_NAME='mytablename') 
   SELECT 1 AS res ELSE SELECT 0 AS res;

第二种方式:

IF OBJECT_ID (N'mytablename', N'U') IS NOT NULL 
   SELECT 1 AS res ELSE SELECT 0 AS res;

MySQL 提供了简单的

SHOW TABLES LIKE '%tablename%'; 

语句。我正在寻找类似的东西。

29 个答案:

答案 0 :(得分:1199)

对于像这样的查询,最好使用INFORMATION_SCHEMA视图。这些视图(大多数)是许多不同数据库的标准视图,很少从版本更改为版本。

要检查表是否存在,请使用:

IF (EXISTS (SELECT * 
                 FROM INFORMATION_SCHEMA.TABLES 
                 WHERE TABLE_SCHEMA = 'TheSchema' 
                 AND  TABLE_NAME = 'TheTable'))
BEGIN
    --Do Stuff
END

答案 1 :(得分:249)

另请注意,如果出于任何原因需要检查临时表,您可以执行此操作:

if OBJECT_ID('tempdb..#test') is not null
 --- temp table exists

答案 2 :(得分:210)

只要我记得

,我们总是使用OBJECT_ID样式
IF OBJECT_ID('*objectName*', 'U') IS NOT NULL 

答案 3 :(得分:109)

请参阅以下方法,

方法1:使用INFORMATION_SCHEMA.TABLES视图

我们可以编写如下的查询来检查当前数据库中是否存在Customers表。

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'Customers')
BEGIN
    PRINT 'Table Exists'
END

方法2:使用OBJECT_ID()函数

我们可以使用如下的OBJECT_ID()函数来检查当前数据库中是否存在Customers表。

IF OBJECT_ID(N'dbo.Customers', N'U') IS NOT NULL
BEGIN
    PRINT 'Table Exists'
END

方法3:使用sys.Objects目录视图

我们可以使用Sys.Objects目录视图来检查Table的存在,如下所示:

IF EXISTS(SELECT 1 FROM sys.Objects WHERE  Object_id = OBJECT_ID(N'dbo.Customers') AND Type = N'U')
BEGIN
   PRINT 'Table Exists'
END

方法4:使用sys.Tables目录视图

我们可以使用Sys.Tables目录视图来检查Table的存在,如下所示:

 IF EXISTS(SELECT 1 FROM sys.Tables WHERE  Name = N'Customers' AND Type = N'U')
 BEGIN
      PRINT 'Table Exists'
 END

方法5:避免使用sys.sysobjects系统表

我们应该避免直接使用sys.sysobjects系统表,在某些未来版本的Sql Server中将不推荐直接访问它。根据Microsoft BOL链接,Microsoft建议直接使用目录视图sys.objects / sys.tables而不是sys.sysobjects系统表。

  IF EXISTS(SELECT name FROM sys.sysobjects WHERE Name = N'Customers' AND xtype = N'U')
  BEGIN
     PRINT 'Table Exists'
  END

参考:http://sqlhints.com/2014/04/13/how-to-check-if-a-table-exists-in-sql-server/

答案 4 :(得分:34)

在不同的数据库中查找表:

if exists (select * from MyOtherDatabase.sys.tables where name = 'MyTable')
    print 'Exists'

答案 5 :(得分:23)

只是想提一下使用OBJECT_ID方法可能会更容易的一种情况。 INFORMATION_SCHEMA视图是每个数据库下的对象 -

  

信息架构视图在名为的特殊架构中定义   INFORMATION_SCHEMA。此架构包含在每个数据库中。

https://msdn.microsoft.com/en-us/library/ms186778.aspx

因此,您使用

访问的所有表格
IF EXISTS (SELECT 1 
           FROM [database].INFORMATION_SCHEMA.TABLES 
           WHERE TABLE_TYPE='BASE TABLE' 
           AND TABLE_NAME='mytablename') 
   SELECT 1 AS res ELSE SELECT 0 AS res;

只会反映[database]中的内容。如果您想检查另一个数据库中的表是否存在,而不是每次都动态更改[database]OBJECT_ID将允许您开箱即用。实施例 -

IF OBJECT_ID (N'db1.schema.table1', N'U') IS NOT NULL 
   SELECT 1 AS res ELSE SELECT 0 AS res;

一样有效
IF OBJECT_ID (N'db2.schema.table1', N'U') IS NOT NULL 
   SELECT 1 AS res ELSE SELECT 0 AS res;

SQL SERVER 2016编辑

从2016年开始,Microsoft通过将if exists个关键字添加到drop语句,简化了在删除之前检查不存在的对象的能力。例如,

drop table if exists mytablename

将在{1>代码中执行与OBJECT_ID / INFORMATION_SCHEMA包装器相同的操作。

https://blogs.msdn.microsoft.com/sqlserverstorageengine/2015/11/03/drop-if-exists-new-thing-in-sql-server-2016/

答案 6 :(得分:20)

IF OBJECT_ID('mytablename') IS NOT NULL 

答案 7 :(得分:15)

使用信息模式是SQL标准的方法,所以它应该被支持它的所有数据库使用。

答案 8 :(得分:10)

如果您需要处理不同的数据库:

DECLARE @Catalog VARCHAR(255)
SET @Catalog = 'MyDatabase'

DECLARE @Schema VARCHAR(255)
SET @Schema = 'dbo'

DECLARE @Table VARCHAR(255)
SET @Table = 'MyTable'

IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES   
    WHERE TABLE_CATALOG = @Catalog 
      AND TABLE_SCHEMA = @Schema 
      AND TABLE_NAME = @Table))
BEGIN
   --do stuff
END

答案 9 :(得分:10)

IF EXISTS 
(
    SELECT   * 
    FROM     sys.objects 
    WHERE    object_id = OBJECT_ID(N'[dbo].[Mapping_APCToFANavigator]') 
             AND 
             type in (N'U')
)
BEGIN

    -- Do whatever you need to here.

END

在上面的代码中,表名是Mapping_APCToFANavigator

答案 10 :(得分:8)

我知道这是一个老问题,但如果你打算经常打电话,我发现了这种可能性。

create procedure Table_Exists
@tbl varchar(50)
as
return (select count(*) from sysobjects where type = 'U' and name = @tbl)
go

答案 11 :(得分:5)

为了开发人员和其他DBA的利益,只需添加此处

接收@Tablename作为参数的脚本

(可能包含或不包含schemaname),如果schema.table存在,则返回以下信息:

the_name                object_id   the_schema  the_table       the_type
[Facts].[FactBackOrder] 758293761   Facts       FactBackOrder   Table

每次我需要测试表或视图是否存在时,我都会在其他脚本中使用此脚本,并且当它出现时,将其object_id用于其他目的。

当您传递空字符串,错误的架构名称或错误的表名时,它会引发错误。

这可以在一个过程中,例如返回-1。

作为一个例子,我有一个名为" Facts.FactBackOrder"在我的一个数据仓库数据库中。

这就是我实现这个目标的方式:

PRINT 'THE SERVER IS ' + @@SERVERNAME
--select db_name()
PRINT 'THE DATABASE IS ' + db_NAME() 
PRINT ''
GO

SET NOCOUNT ON
GO

--===================================================================================
-- @TableName is the parameter
-- the object we want to deal with (it might be an indexed view or a table)
-- the schema might or might not be specified
-- when not specified it is DBO
--===================================================================================

DECLARE @TableName SYSNAME

SELECT @TableName = 'Facts.FactBackOrder'
--===================================================================================
--===================================================================================
DECLARE @Schema SYSNAME
DECLARE @I INT
DECLARE @Z INT 

SELECT @TableName = LTRIM(RTRIM(@TableName))
SELECT @Z = LEN(@TableName)

IF (@Z = 0) BEGIN

            RAISERROR('Invalid @Tablename passed.',16,1)

END 

SELECT @I = CHARINDEX('.',@TableName )
--SELECT @TableName ,@I

IF @I > 0 BEGIN

        --===================================================================================
        -- a schema and table name have been passed
        -- example Facts.FactBackOrder 
        -- @Schema = Fact
        -- @TableName = FactBackOrder
        --===================================================================================

   SELECT @Schema    = SUBSTRING(@TABLENAME,1,@I-1)
   SELECT @TableName = SUBSTRING(@TABLENAME,@I+1,@Z-@I)



END
ELSE BEGIN

        --===================================================================================
        -- just a table name have been passed
        -- so the schema will be dbo
        -- example Orders
        -- @Schema = dbo
        -- @TableName = Orders
        --===================================================================================

   SELECT @Schema    = 'DBO'     


END

        --===================================================================================
        -- Check whether the @SchemaName is valid in the current database
        --===================================================================================

IF NOT EXISTS ( SELECT * FROM INFORMATION_SCHEMA.SCHEMATA K WHERE K.[SCHEMA_NAME] = @Schema ) BEGIN

            RAISERROR('Invalid Schema Name.',16,1)

END 

--SELECT @Schema  as [@Schema]
--      ,@TableName as [@TableName]


DECLARE @R1 TABLE (

   THE_NAME SYSNAME
  ,THE_SCHEMA SYSNAME
  ,THE_TABLE SYSNAME
  ,OBJECT_ID INT
  ,THE_TYPE SYSNAME
  ,PRIMARY KEY CLUSTERED (THE_SCHEMA,THE_NAME)

)

;WITH RADHE_01 AS (
SELECT QUOTENAME(SCHEMA_NAME(O.schema_id)) + '.' + QUOTENAME(O.NAME) AS [the_name]
      ,the_schema=SCHEMA_NAME(O.schema_id)
      ,the_table=O.NAME
      ,object_id =o.object_id 
      ,[the_type]= CASE WHEN O.TYPE = 'U' THEN 'Table' ELSE 'View' END 
from sys.objects O
where O.is_ms_shipped = 0
AND O.TYPE IN ('U','V')
)
INSERT INTO @R1 (
   THE_NAME 
  ,THE_SCHEMA 
  ,THE_TABLE 
  ,OBJECT_ID
  ,THE_TYPE 
)
SELECT  the_name
       ,the_schema
       ,the_table
       ,object_id
       ,the_type
FROM RADHE_01
WHERE the_schema = @Schema 
  AND the_table  = @TableName

IF (@@ROWCOUNT = 0) BEGIN 

             RAISERROR('Invalid Table Name.',16,1)

END 
ELSE BEGIN

    SELECT     THE_NAME 
              ,THE_SCHEMA 
              ,THE_TABLE 
              ,OBJECT_ID
              ,THE_TYPE 

    FROM @R1

END 

答案 12 :(得分:4)

SQL Server 2000 中,您可以尝试:

IF EXISTS(SELECT 1 FROM sysobjects WHERE type = 'U' and name = 'MYTABLENAME')
BEGIN
   SELECT 1 AS 'res' 
END

答案 13 :(得分:3)

    IF OBJECT_ID (N'dbo.T', N'U') IS NOT NULL 
      BEGIN 
          print 'deleted table';
          drop table t 
      END
    else 
      begin 
          print 'table not found' 
      end

Create table t (id int identity(1,1) not null, name varchar(30) not null, lastname varchar(25) null)
insert into t( name, lastname) values('john','doe');
insert into t( name, lastname) values('rose',NULL);

Select * from t
1   john    doe
2   rose    NULL

-- clean
drop table t

答案 14 :(得分:3)

IF EXISTS 
(
    SELECT  * 

    FROM    INFORMATION_SCHEMA.TABLES 

    WHERE   TABLE_SCHEMA = 'PutSchemaHere'     
            AND  
            TABLE_NAME   = 'PutTableNameHere'
)

答案 15 :(得分:2)

对于尚未找到解决方案的人来说,重要的是要知道的事情: SQL server!= MYSQL 。 如果你想用 MYSQL 来做,那很简单

    $sql = "SELECT 1 FROM `db_name`.`table_name` LIMIT 1;";
    $result = mysql_query($sql);
    if( $result == false )
        echo "table DOES NOT EXIST";
    else
        echo "table exists";

在此发布此消息是因为它是Google的热门话题。

答案 16 :(得分:2)

您可以使用以下代码

IF (OBJECT_ID('TableName') IS NOT NULL )
BEGIN
  PRINT 'Table Exists'
END
ELSE
BEGIN 
  PRINT 'Table NOT Exists'
END

IF (EXISTS (SELECT * FROM sys.tables WHERE [name] = 'TableName'))
BEGIN
  PRINT 'Table Exists'
END
ELSE
BEGIN 
  PRINT 'Table NOT Exists'
END

答案 17 :(得分:1)

IF EXISTS (   SELECT * FROM   dbo.sysobjects WHERE  id = OBJECT_ID(N'dbo.TableName') AND OBJECTPROPERTY(id, N'IsUserTable') = 1 )
BEGIN
  SELECT * FROM dbo.TableName;
END
GO

答案 18 :(得分:1)

IF EXISTS (
SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE 
TABLE_CATALOG = 'Database Name' and
TABLE_NAME = 'Table Name' and 
TABLE_SCHEMA = 'Schema Name') -- Database and Schema name in where statement can be deleted

BEGIN
--TABLE EXISTS
END

ELSE BEGIN
--TABLE DOES NOT EXISTS
END

答案 19 :(得分:1)

select name from SysObjects where xType='U' and name like '%xxx%' order by name

答案 20 :(得分:1)

我以这里创建视图为例

因为ALTER / CREATE命令不能在BEGIN / END块内。您需要先测试是否存在,然后再删除它

IF Object_ID('TestView') IS NOT NULL
DROP VIEW TestView

GO

CREATE VIEW TestView
   as
   . . .

GO

如果您担心丢失的权限,也可以编写GRANT语句的脚本,然后在末尾重新运行。

您可以将create / alter打包为一个字符串,然后执行EXEC-对于大视图来说可能很难看

DECLARE @SQL as varchar(4000)

-- set to body of view
SET @SQL = 'SELECT X, Y, Z FROM TABLE' 

IF Object_ID('TestView') IS NULL
    SET @SQL = 'CREATE VIEW TestView AS ' + @SQL
ELSE    
    SET @SQL = 'ALTER VIEW TestView AS ' + @SQL

答案 21 :(得分:0)

还有一个选项可以检查表是否存在于数据库中

IF EXISTS(SELECT 1 FROM [change-to-your-database].SYS.TABLES WHERE NAME = 'change-to-your-table-name')
BEGIN
    -- do whatever you want
END

答案 22 :(得分:0)

如果这是“终极”讨论,那么应该注意的是,如果服务器是链接的,Larry Leonard的脚本也可以查询远程服务器。

if exists (select * from REMOTE_SERVER.MyOtherDatabase.sys.tables where name = 'MyTable')
    print 'Exists'

答案 23 :(得分:0)

运行此查询以检查数据库中是否存在表:

IF(SELECT TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'YourTableName') IS NOT NULL
PRINT 'Table Exists';

答案 24 :(得分:0)

从INFORMATIONAL_SCHEME和OBJECT_ID中选择时,我遇到了一些问题。我不知道这是ODBC驱动程序还是其他问题。.来自SQL Management Studio的查询都可以。

这是解决方案:

SELECT COUNT(*) FROM <yourTableNameHere>

因此,如果查询失败,则数据库中可能没有这样的表(或者您没有对此表的访问权限)。

通过比较处理ODBC驱动程序的SQL执行程序返回的值(在我的情况下为整数)来完成检查。

if (sqlexec(conectionHandle, 'SELECT COUNT(*) FROM myTable') == -1) {
  // myTable doesn't exist..
}

答案 25 :(得分:0)

- 创建程序以检查表是否存在

DELIMITER $$

DROP PROCEDURE IF EXISTS `checkIfTableExists`;

CREATE PROCEDURE checkIfTableExists(
    IN databaseName CHAR(255),
    IN tableName CHAR(255),
    OUT boolExistsOrNot CHAR(40)
)

  BEGIN
      SELECT count(*) INTO boolExistsOrNot FROM information_schema.TABLES
      WHERE (TABLE_SCHEMA = databaseName)
      AND (TABLE_NAME = tableName);
  END $$

DELIMITER ;

- - 如何使用:检查表迁移是否存在

 CALL checkIfTableExists('muDbName', 'migrations', @output);

答案 26 :(得分:0)

如果有人试图在linq to sql(或特别是linqpad)中执行相同的操作,请启用选项以包含系统表和视图并执行以下代码:

let oSchema = sys.Schemas.FirstOrDefault(s=>s.Name==a.schema )
where oSchema !=null
let o=oSchema!=null?sys.Objects.FirstOrDefault (o => o.Name==a.item && o.Schema_id==oSchema.Schema_id):null
where o!=null

假设您在名为item的属性中有一个名称的对象,以及名为schema的属性中的模式,其中源变量名称为a

答案 27 :(得分:-1)

我总是这样检查。

IF OBJECT_ID('TestXML..tblCustomer') IS NOT NULL  
BEGIN  
    PRINT 'Exist'
END  
ELSE
BEGIN
    PRINT 'Not Exist'
END 

谢谢

答案 28 :(得分:-6)

在一个数据库中考虑你有一个表t1。你想在其他数据库上运行脚本 - 如果t1存在则不做任何其他创建t1。 要做到这一点,打开visual studio并执行以下操作:

右键单击t1,然后右键单击脚本表,然后单击DROP和Create To,再单击New Query Editor

您将找到所需的查询。但在执行该脚本之前,不要忘记在查询中注释掉drop语句,因为如果已经存在,则不想创建新语句。

由于