Проверьте, существует ли таблица, и если она не существует, создайте ее в SQL Server 2008.


130

Я пишу хранимую процедуру в SQL Server 2008. Мне нужно проверить, существует ли таблица в базе данных. Если нет, то мне нужно его создать.

Как мне это сделать?


2
Связанные, если не повторяющиеся: проверьте, существует ли таблица в SQL Server .

1
Это отличный вопрос, который в конце концов задаст всем, кто работает с SQL Server. Печально, что в SQL Server нет дружественного стиля Oracle CREATE OR REPLACE
Давос

1
Для MySQL вы можете использоватьCREATE TABLE IF NOT EXISTS ...
Джон Хенкель

Ответы:


150

Что-то вроде этого

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' вместо type in (N'U ') (столбец _type имеет тип char, используя 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 07

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 переносимы между разными системами СУБД, поэтому перенос на разные СУБД не требует никаких изменений.

Подход 2: использование функции OBJECT_ID ()

Мы можем использовать OBJECT_ID()функцию, как показано ниже, чтобы проверить, существует ли таблица tblTest в текущей базе данных.

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

Указание частей имени базы данных и имени схемы для имени таблицы необязательно. Но указание имени базы данных и имени схемы дает возможность проверить существование таблицы в указанной базе данных и в указанной схеме, вместо проверки текущей базы данных по всем схемам. Приведенный ниже запрос показывает, что даже если текущая база данных является ГЛАВНОЙ базой данных, мы можем проверить наличие tblTestтаблицы в dboсхеме в 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.Objectsкаталога, представление Sys.objectsкаталога упоминается как базовое представление, а sys.Tablesкак производное представление. Sys.Tablesвернет строки только для объектов таблицы, тогда как Sys.Objectпредставление, помимо возврата строк для объектов таблицы, возвращает строки для таких объектов, как: хранимая процедура, представления и т. д.

Подход 5: избегайте использования системной таблицы sys.sysobjects

Мы должны избегать sys.sysobjectsпрямого использования системной таблицы, прямой доступ к ней будет устаревшим в некоторых будущих версиях 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

3
IF (EXISTS (SELECT * 
                 FROM INFORMATION_SCHEMA.TABLES 
                 WHERE  TABLE_NAME = 'd020915'))
BEGIN
  declare @result int
  set @result=1
  select @result as result
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.objects, sys.tables) для кода, который будет нацеливаться только на экземпляры SQL Server 2008, и представления информационной схемы (например information_schema.tables) для кода, который должен быть переносимым. Дополнительную информацию о различных представлениях можно найти здесь: Запрос системного каталога SQL Server
ajk

-2

Если я не ошибаюсь, это должно сработать:

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

2
что, если таблица существует, но пуста, в этом случае это будет верно
SQLMenace

@SQLMeance О, хорошо, из вашего ответа я понимаю, что вы проверяете тип «U» в sys.objects. Не могли бы вы помочь мне понять, почему вы рекомендуете это? и может ли таблица существовать где-нибудь еще? Заранее
благодарю
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.