Check if table exists in SQL Server
我希望这是关于如何使用SQL语句检查SQL Server 2000/2005中是否存在表的最终讨论。
当你用谷歌搜索答案时,你会得到很多不同的答案。有没有一种正式的/前后兼容的方式?
有两种可能的方法。这两种方法中的哪一种是标准的/最好的?
第一种方式:
1 2 3 4 5 | 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; |
第二种方式:
1 2 | IF OBJECT_ID (N'mytablename', N'U') IS NOT NULL SELECT 1 AS res ELSE SELECT 0 AS res; |
mysql提供了
1 | SHOW TABLES LIKE '%tablename%'; |
语句。我在找类似的东西。
对于这样的查询,最好使用
要检查表是否存在,请使用:
1 2 3 4 5 6 7 | IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'TheSchema' AND TABLE_NAME = 'TheTable')) BEGIN --Do Stuff END |
还要注意,如果出于任何原因需要检查临时表,可以执行以下操作:
1 2 | if OBJECT_ID('tempdb..#test') is not null --- temp table exists |
我记得我们一直使用
1 | IF OBJECT_ID('*objectName*', 'U') IS NOT NULL |
请看下面的方法,
方法1:使用information_schema.tables视图
我们可以编写如下查询来检查当前数据库中是否存在客户表。
1 2 3 4 | IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'Customers') BEGIN PRINT 'Table Exists' END |
方法2:使用object_id()函数
我们可以使用如下的object_id()函数来检查当前数据库中是否存在customers表。
1 2 3 4 | IF OBJECT_ID(N'dbo.Customers', N'U') IS NOT NULL BEGIN PRINT 'Table Exists' END |
方法3:使用sys.objects目录视图
我们可以使用sys.objects目录视图检查表的存在,如下所示:
1 2 3 4 | 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目录视图检查表的存在,如下所示:
1 2 3 4 | 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系统表。
1 2 3 4 | 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/
在其他数据库中查找表:
1 2 | if exists (select * from MyOtherDatabase.sys.tables where name = 'MyTable') print 'Exists' |
只是想提到一种情况,在这种情况下,使用
The information schema views are defined in a special schema named
INFORMATION_SCHEMA. This schema is contained in each database.
https://msdn.microsoft.com/en-us/library/ms186778.aspx
因此,使用
1 2 3 4 5 | 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; |
只反映
1 2 | IF OBJECT_ID (N'db1.schema.table1', N'U') IS NOT NULL SELECT 1 AS res ELSE SELECT 0 AS res; |
同样有效
1 2 | 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年开始,微软通过在
1 | drop table if exists mytablename |
将在1行代码中执行与
1 | IF OBJECT_ID('mytablename') IS NOT NULL |
使用信息模式是SQL的标准方法,因此所有支持它的数据库都应该使用它。
如果需要处理不同的数据库:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 |
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
在上面的代码中,表名是
我知道这是一个古老的问题,但如果你打算经常打电话给我,我发现了这种可能性。
1 2 3 4 5 | create procedure Table_Exists @tbl varchar(50) as return (select count(*) from sysobjects where type = 'U' and name = @tbl) go |
为了开发人员和DBA同事的利益,只需在这里添加
接收@tablename作为参数的脚本
(可能包含架构名称,也可能不包含架构名称),如果存在schema.table,则返回以下信息:
1 2 | the_name object_id the_schema the_table the_type [Facts].[FactBackOrder] 758293761 Facts FactBackOrder Table |
每次我需要测试一个表或视图是否存在时,我都会生成这个脚本,在其他脚本中使用它,当它存在时,我会让它的对象ID用于其他目的。
当您传递空字符串、错误的架构名或错误的表名时,它会引发错误。
这可能在一个过程中,例如返回-1。
例如,我的一个数据仓库数据库中有一个名为"facts.factbackorder"的表。
我就是这样做到的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | 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 |
在SQL Server 2000中,您可以尝试:
1 2 3 4 | IF EXISTS(SELECT 1 FROM sysobjects WHERE type = 'U' and name = 'MYTABLENAME') BEGIN SELECT 1 AS 'res' END |
1 2 3 4 5 6 7 8 9 10 | IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PutSchemaHere' AND TABLE_NAME = 'PutTableNameHere' ) |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 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!= MySQL。如果你想用MySQL来做,这很简单
1 2 3 4 5 6 | $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"; |
把这个贴在这里,因为它是谷歌的热门。
1 | select name from SysObjects where xType='U' and name like '%xxx%' order by name |
1 2 3 4 5 | 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 |
我在选择信息方案和对象ID时遇到了一些问题。我不知道这是ODBC驱动程序的问题还是其他问题。来自SQL Management Studio的查询都正常。
解决方案如下:
1 | SELECT COUNT(*) FROM <yourTableNameHere> |
因此,如果查询失败,那么数据库中可能没有这样的表(或者您没有访问它的权限)。
检查是通过比较处理ODBC驱动程序的SQL执行器返回的值(在我的例子中是整数)来完成的。
1 2 3 | if (sqlexec(conectionHandle, 'SELECT COUNT(*) FROM myTable') == -1) { // myTable doesn't exist.. } |
如果这是"终极"讨论,那么应该注意的是,Larry Leonard的脚本也可以查询远程服务器(如果服务器链接)。
1 2 | if exists (select * from REMOTE_SERVER.MyOtherDatabase.sys.tables where name = 'MyTable') print 'Exists' |
----创建检查表是否存在的过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 ; |
----如何使用:检查表迁移是否存在
1 | CALL checkIfTableExists('muDbName', 'migrations', @output); |
如果有人试图在Linq to SQL(或尤其是LinqPad)中执行相同的操作,请启用包含系统表和视图的选项,并执行以下代码:
1 2 3 4 | 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的属性中有一个名称为
考虑在一个数据库中有一个表T1。您希望在其他数据库上运行脚本,例如-如果存在T1,则不执行任何其他操作创建T1。要执行此操作,请打开Visual Studio并执行以下操作:
右键单击T1,然后编写表脚本为,然后删除并创建到,然后新建查询编辑器。
您将找到所需的查询。但在执行该脚本之前,不要忘记注释掉查询中的drop语句,因为如果已经有了该语句,就不希望创建新语句。
谢谢