Перевірте, чи існує таблиця та чи не існує, створіть її в SQL Server 2008


130

Я пишу збережену процедуру в SQL Server 2008. Мені потрібно перевірити, чи існує таблиця в базі даних. Якщо цього немає, мені потрібно створити його.

Як це зробити?


2
Пов'язані, якщо не дублюючі: Перевірте, чи існує таблиця в SQL Server .

1
Це чудове питання, яке врешті-решт зададуть всі, хто працює з SQL Server. Сумно, що у SQL Server немає доброзичливого стилю Oracle СТВОРИТИ АБО ЗАМІНУ
Davos

1
Для MySQL ви можете скористатисяCREATE TABLE IF NOT EXISTS ...
John Henckel

Відповіді:


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' замість типу in (N'U ') ( тип стовпця типу типу 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 vs. sysobjects vs. sys.all_objects vs. 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

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, ми можемо перевірити наявність 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 Catalogue View

Ми можемо використовувати подання 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повертає рядки лише для об'єктів Table, тоді як Sys.Objectперегляд крім повернення рядків для об'єктів таблиці, він повертає рядки для об'єктів типу: збережена процедура, представлення даних тощо.

Підхід 5: Уникайте використання системної таблиці sys.sysobjects

Ми повинні уникати використання sys.sysobjectsсистемної таблиці безпосередньо, у деяких майбутніх версіях сервера Sql буде закритий прямий доступ до неї. Відповідно до посилання [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
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.