检查SQL Server中是否存在表

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

当你回答Google时,你会得到很多不同的答案。 有没有官方/向前兼容的方式来做到这一点?

这里有两种可能的方式来做到这一点。 哪一个是标准/最好的方法呢?

第一种方法:

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%' ; 声明。 我正在寻找类似的东西。

对于这样的查询,最好使用INFORMATION_SCHEMA视图。 这些视图(大部分)是跨许多不同数据库的标准,很less从版本变为版本。

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

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

另外请注意,如果出于任何原因,您需要检查一个临时表,你可以这样做:

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

只要我记得,我们总是使用OBJECT_ID风格

 IF OBJECT_ID('*objectName*', 'U') IS NOT NULL 

请看下面的方法,

方法1:使用INFORMATION_SCHEMA.TABLES视图

我们可以像下面这样写一个查询来检查当前数据库中是否存在客户表。

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

方法2:使用OBJECT_ID()函数

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

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

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

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

 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目录视图来检查表的存在,如下所示:

  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链接,Microsoftbuild议直接使用目录视图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/

在另一个数据库上查找表:

 if exists (select * from MyOtherDatabase.sys.tables where name = 'MyTable') print 'Exists' 
 IF OBJECT_ID('mytablename') IS NOT NULL 

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

只是想提一下使用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] 。 如果您想检查另一个数据库中的表是否存在,而不是每次dynamic更改[database] ,那么OBJECT_ID将允许您立即执行此操作。 EX-

 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年开始,微软通过将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/

 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

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

 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 

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

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

只是在这里添加,为开发人员和同行DBA的利益

接收@Tablename作为参数的脚本

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

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

我生成了这个脚本,用在其他脚本里面,每当我需要testing一个表或视图是否存在时,以及何时得到它的object_id被用于其他目的。

当您传递空string,错误的模式名称或错误的表名称时,会引发错误。

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

作为一个例子,我在我的一个Data Warehouse数据库中有一个名为“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 
 IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PutSchemaHere' AND TABLE_NAME = 'PutTableNameHere' ) 
  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 

SQL Server 2000中,您可以尝试:

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

如果有人试图在LINQ到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的属性中的模式的源variables名称是

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

对于还没有find解决scheme的人来说,重要的是要知道: 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"; 

在这里发表,因为这是在谷歌的热门。

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

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

– 创build过程来检查表是否存在


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

考虑在一个数据库中你有一张表t1。 你想在其他数据库上运行脚本,比如 – 如果t1存在,那么别的什么都不要做。 要做到这一点打开视觉工作室,并执行以下操作:

右键单击t1,然后selectScript table,然后DROP和Create To,然后新build查询编辑器

你会发现你想要的查询。 但在执行该脚本之前,不要忘记在查询中注释掉drop语句,因为如果已经存在一个,则不需要创build新语句。

谢谢