Sprawdź, czy tabela istnieje, a jeśli nie, utwórz ją w programie SQL Server 2008


135

Piszę procedurę składowaną w SQL Server 2008. Muszę sprawdzić, czy tabela istnieje w bazie danych. Jeśli tak nie jest, muszę go utworzyć.

Jak mam to zrobic?


2
Powiązane, jeśli nie są zduplikowane: Sprawdź, czy tabela istnieje w SQL Server .

1
To świetne pytanie, które w końcu zada każdy pracujący z SQL Server. To smutne, że SQL Server nie ma przyjaznego stylu Oracle UTWÓRZ LUB WYMIEN
Davos

1
W przypadku MySQL możesz użyćCREATE TABLE IF NOT EXISTS ...
John Henckel

Odpowiedzi:


157

Coś takiego

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
z szacunkiem rozważ kilka zmian (ze względu na plan wykonania), używając pola indeksowanego zamiast * (identyfikator_obiektu jest polem numerycznym powszechnie przywoływanym w tej tabeli) użyj type = 'U' zamiast type in (N'U ') (kolumna _type jest typu char przy użyciu Nchar powoduje niejawną konwersję, która często powoduje problemy z estymatorem kardynalności)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

156

Dla kontrastu lubię używać funkcji object_id, jak pokazano poniżej. Jest trochę łatwiejszy do odczytania i nie musisz się martwić o sys.objects, sysobjects, sys.all_objects i sys.tables. Podstawowa forma:

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

Oczywiście będzie to pokazać jako „Present”, jeśli istnieje jakikolwiek obecny obiekt o tej nazwie. Jeśli chcesz sprawdzić tylko tabele, potrzebujesz:

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

Działa również w przypadku tabel tymczasowych:

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

2
Zwykle widzę inną używaną metodę (sprawdzanie tabel sys), ale wydaje się ona bardziej czytelna i zwarta. czy jest jakiś powód, aby nie preferować tej metody od zaakceptowanej odpowiedzi? (Na przykład problemy ze zgodnością z migracją SQL do różnych dostawców bazy danych, szybkością itp.)?
jedd.ahyoung

16

Utwórzmy przykładową bazę danych z tabelą według poniższego skryptu:

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

Podejście 1: Korzystanie z widoku INFORMATION_SCHEMA.TABLES

Możemy napisać zapytanie jak poniżej, aby sprawdzić, czy tabela tblTest istnieje w bieżącej bazie danych.

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

Powyższe zapytanie sprawdza istnienie tabeli tblTest we wszystkich schematach w bieżącej bazie danych. Zamiast tego, jeśli chcesz sprawdzić istnienie tabeli w określonym schemacie i określonej bazie danych, możemy napisać powyższe zapytanie jak poniżej:

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

Zalety tego podejścia: widoki INFORMATION_SCHEMA można przenosić między różnymi systemami RDBMS, więc przenoszenie do różnych systemów RDBMS nie wymaga żadnych zmian.

Podejście 2: Korzystanie z funkcji OBJECT_ID ()

Możemy użyć OBJECT_ID()funkcji jak poniżej, aby sprawdzić, czy tabela tblTest istnieje w bieżącej bazie danych.

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

Określenie części nazwy bazy danych i nazwy schematu dla nazwy tabeli jest opcjonalne. Jednak określenie nazwy bazy danych i nazwy schematu umożliwia sprawdzenie istnienia tabeli w określonej bazie danych i w określonym schemacie, zamiast sprawdzania bieżącej bazy danych we wszystkich schematach. Poniższe zapytanie pokazuje, że mimo że aktualna baza danych jest bazą MASTER, możemy sprawdzić istnienie tblTesttabeli w dboschemacie w Testbazie danych.

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

Zalety: łatwe do zapamiętania. Kolejną godną uwagi kwestią, o której należy wspomnieć o OBJECT_ID()funkcji, jest: zapewnia opcję sprawdzenia istnienia tabeli tymczasowej, która jest tworzona w kontekście bieżącego połączenia. Wszystkie inne podejścia sprawdzają istnienie tabeli tymczasowej utworzonej we wszystkich kontekstach połączeń, a nie tylko w bieżącym kontekście połączenia. Poniższe zapytanie pokazuje, jak sprawdzić istnienie tabeli tymczasowej za pomocą OBJECT_ID()funkcji:

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

Podejście 3: Korzystanie z widoku katalogu sys.Objects

Możemy użyć Sys.Objectswidoku katalogu, aby sprawdzić istnienie tabeli, jak pokazano poniżej:

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

Podejście 4: Korzystanie z widoku katalogu sys.Tables

Możemy użyć Sys.Tableswidoku katalogu, aby sprawdzić istnienie tabeli, jak pokazano poniżej:

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

Sys.Tableswidok katalogu dziedziczy wiersze z Sys.Objectswidoku katalogu, widok Sys.objectskatalogu jest określany jako widok bazowy, gdzie sys.Tablesjest nazywany widokiem pochodnym. Sys.Tableszwróci wiersze tylko dla obiektów tabeli, podczas gdy Sys.Objectview oprócz wierszy dla obiektów tabeli zwróci wiersze dla obiektów takich jak: procedura składowana, widoki itp.

Podejście 5: Unikaj używania sys.sysobjects Tabela systemowa

Powinniśmy unikać sys.sysobjectsbezpośredniego korzystania z tabeli systemowej, bezpośredni dostęp do niej będzie przestarzały w niektórych przyszłych wersjach Sql Server. Zgodnie z odsyłaczem [Microsoft BOL] [1], Microsoft sugeruje użycie widoków katalogu sys.objects/sys.tableszamiast sys.sysobjectsbezpośrednio tabeli systemowej.

IF EXISTS(SELECT name FROM sys.sysobjects WHERE Name = N'tblTest' AND xtype = N'U')
BEGIN
  PRINT 'Table Exists'
END

Źródła: http://sqlhints.com/2014/04/13/how-to-check-if-a-table-exists-in-sql-server/


Należy zauważyć, że ta odpowiedź określa, które podejście wymaga określenia bazy danych, a które nie. Jest to niezwykle cenne i w przypadku skryptów uruchamianych w celu skonfigurowania i zaktualizowania operacyjnej bazy danych, gdy na tej samej instancji działa wiele takich samych baz danych, to jest klucz! Świetna informacja.
Nelda.techspiress

12

EDYTOWANO

Możesz zajrzeć do sys.tables, aby sprawdzić istnienie żądanej tabeli:

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
Witamy w StackOverflow. Odpowiadając na pytania, rozważ również dodanie wyjaśnienia. Sam kod w większości przypadków nie jest zbyt pomocny.
Viktor

0

Wypróbuj następującą instrukcję, aby sprawdzić istnienie tabeli w bazie danych:

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

Możesz utworzyć tabelę wewnątrz bloku if.


3
Chociaż ta składnia będzie działać, sysobjectsjest to widok zgodności, który istnieje tylko po to, aby uniknąć uszkodzenia starszego kodu. Moja sugestia byłoby użycie widoków katalogu systemowego (np sys.objects, sys.tables) dla kodu, który będzie kierowanych wyłącznie instancji SQL Server 2008 oraz widokiem schematu informacje (np information_schema.tables) do kodu, który musi być przenośny. Więcej informacji na temat różnych widoków można znaleźć tutaj: Wykonywanie zapytań do katalogu systemu SQL Server
ajk

-2

Jeśli się nie mylę, to powinno działać:

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

2
co jeśli tabela istnieje, ale jest pusta, w takim przypadku będzie to prawdą
SQLMenace

@SQLMeance O ok, rozumiem z twojej odpowiedzi, że sprawdzasz typ „U” w sys.objects, czy możesz mi pomóc zrozumieć, dlaczego to polecasz? i czy stół może istnieć gdziekolwiek indziej? Z góry
dziękuję
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.