检查表是否存在,如果不存在,请在SQL Server 2008中创建表


130

我在SQL Server 2008中编写存储过程。我需要检查数据库中是否存在表。如果没有,那么我需要创建它。

我该怎么做呢?


2
相关(如果不重复):检查SQL Server中是否存在表

1
这是一个很好的问题,每个使用SQL Server的人最终都会问。令人遗憾的是,SQL Server没有友好的Oracle风格CREATE OR REPLACE
Davos

1
对于MySQL,您可以使用CREATE TABLE IF NOT EXISTS ...
John Henckel

Answers:


148

像这样

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

BEGIN
CREATE TABLE [dbo].[YourTable](
    ....
    ....
    ....
) 

END

1
仔细考虑使用索引字段而不是*(object_id是此表中通常引用的数字字段)(出于执行计划的考虑)的一些更改,请使用type ='U'而不是(N'U')中类型(列_typechar类型,使用Nchar会导致隐式转换,这通常会导致基数估计器出现问题)if (not exists (select object_id from sys.objects where object_id = OBJECT_ID(N'[dbo].[client_tgi_g67_period_list]') and type = 'U'))
yeOldeDataSmythe

153

只是为了对比,我喜欢使用object_id函数,如下所示。它更容易阅读,而且您不必担心sys.objects与sysobjects与sys.all_objects与sys.tables的关系。基本形式:

IF object_id('MyTable') is not null
    PRINT 'Present!'
ELSE
    PRINT 'Not accounted for'

当然,如果存在任何使用该名称的对象,它将显示为“存在” 。如果您只想检查表,则需要:

IF object_id('MyTable', 'U') is not null
    PRINT 'Present!'
ELSE
    PRINT 'Not accounted for'

它也适用于临时表:

IF object_id('tempdb.dbo.#MyTable') is not null
    PRINT 'Present!'
ELSE
    PRINT 'Not accounted for'

2
我通常会看到使用的另一种方法(检查sys表),但这看起来既清晰又紧凑。有什么理由不喜欢这种方法而不是公认的答案?(例如与SQL迁移到不同数据库提供程序的兼容性问题,速度等)?
jedd.ahyoung 2014年

16

让我们通过以下脚本用表创建示例数据库:

CREATE DATABASE Test
GO
USE Test
GO
CREATE TABLE dbo.tblTest (Id INT, Name NVARCHAR(50))

方法1:使用INFORMATION_SCHEMA.TABLES视图

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

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

上面的查询检查当前数据库中所有模式之间tblTest表是否存在。如果您要检查指定模式和指定数据库中表的存在,则可以使用以下查询代替:

IF EXISTS (SELECT * FROM Test.INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = N'dbo'  AND TABLE_NAME = N'tblTest')
BEGIN
  PRINT 'Table Exists'
END

这种方法的优点:INFORMATION_SCHEMA视图可在不同的RDBMS系统之间移植,因此移植到不同的RDBMS不需要任何更改。

方法2:使用OBJECT_ID()函数

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

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

为表名称指定数据库名称和架构名称部分是可选的。但是,指定“数据库名称”和“模式名称”提供了一个选项,可以检查表在指定数据库中以及在指定模式中是否存在,而不是在所有模式中都检查当前数据库。以下查询表明,即使当前数据库是MASTER数据库,我们也可以检查数据库tblTestdbo架构中表的存在Test

USE MASTER
GO
IF OBJECT_ID(N'Test.dbo.tblTest', N'U') IS NOT NULL
BEGIN
  PRINT 'Table Exists'
END

优点:容易记住。关于OBJECT_ID()功能需要提及的另一个值得注意的点是:它提供了一种检查在当前连接上下文中创建的临时表是否存在的选项。所有其他方法都检查是否存在跨所有连接上下文创建的临时表,而不仅仅是当前连接上下文。以下查询显示了如何使用OBJECT_ID()函数检查临时表的存在:

CREATE TABLE #TempTable(ID INT)
GO
IF OBJECT_ID(N'TempDB.dbo.#TempTable', N'U') IS NOT NULL
BEGIN
  PRINT 'Table Exists'
END
GO

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

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

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

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

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

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

Sys.Tables目录视图继承了目录视图中的行Sys.ObjectsSys.objects目录视图称为基本视图,其中sys.Tables称为派生视图。Sys.Tables将仅返回Table对象Sys.Object的行,而view除了返回table对象的行之外,还返回对象的行,例如:存储过程,视图等。

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

我们应该避免sys.sysobjects直接使用System Table,否则在某些将来的Sql Server版本中将不建议直接使用它。按照[Microsoft BOL] [1]链接,Microsoft建议直接使用目录视图sys.objects/sys.tables而不是sys.sysobjects系统表。

IF EXISTS(SELECT name FROM sys.sysobjects WHERE Name = N'tblTest' 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/


重要的是要注意,此答案提供了需要指定数据库的哪种方法,哪些不需要。这是非常有价值的,并且对于在同一实例上运行多个相同数据库的情况下运行以设置和更新可操作数据库的脚本,这是关键!很好的信息。
Nelda.techspiress

11

已编辑

您可以查看sys.tables来检查是否存在所需的表:

IF  NOT EXISTS (SELECT * FROM sys.tables
WHERE name = N'YourTable' AND type = 'U')

BEGIN
CREATE TABLE [SchemaName].[YourTable](
    ....
    ....
    ....
) 

END


1
Declare @Username varchar(20)
Set @Username = 'Mike'

if not exists 
(Select * from INFORMATION_SCHEMA.TABLES where TABLE_NAME = 'tblEmp')

Begin
    Create table tblEmp (ID int primary key, Name varchar(50))
    Print (@Username + ' Table created successfully')
End

Else

Begin
    Print (@Username + ' : this Table Already exists in the database')
End

1
欢迎使用StackOverflow。在回答问题时,也应考虑添加说明。在大多数情况下,仅靠代码并不是很有帮助。
维克多

0

尝试使用以下语句来检查数据库中是否存在表:

If not exists (select name from sysobjects where name = 'tablename')

您可以在if块内创建表。


3
尽管该语法将起作用,但它sysobjects是一个兼容性视图,仅用于避免破坏较旧的代码。我的建议是使用系统目录视图(例如sys.objectssys.tables)的代码,将只针对的SQL Server 2008个实例,以及信息架构视图(如information_schema.tables代码)需要被移植。您可以在此处找到有关不同视图的更多信息:查询SQL Server系统目录
ajk 2011年

-2

如果我没看错,这应该可行:

    if not exists (Select 1 from tableName)
create table ...

2
如果表存在但为空怎么办,在这种情况下将是正确的
SQLMenace 2011年

@SQLMeance哦,好的,我从您的回答中了解到您正在检查sys.objects中的'U'类型,请您帮我理解,为什么建议您这样做?表格可以存在于其他任何地方吗?预先谢谢您
-RaM
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.