Überprüfen Sie, ob eine Tabelle vorhanden ist, und erstellen Sie sie in SQL Server 2008, falls sie nicht vorhanden ist


130

Ich schreibe eine gespeicherte Prozedur in SQL Server 2008. Ich muss überprüfen, ob eine Tabelle in der Datenbank vorhanden ist. Wenn nicht, muss ich es erstellen.

Wie mache ich das?



1
Dies ist eine großartige Frage, die sich jeder, der mit SQL Server arbeitet, irgendwann stellen wird. Es ist traurig, dass SQL Server nicht den freundlichen Oracle-Stil CREATE OR REPLACE
Davos

1
Für MySQL können Sie verwendenCREATE TABLE IF NOT EXISTS ...
John Henckel

Antworten:


148

Etwas wie das

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
Berücksichtigen Sie einige Änderungen (im Interesse des Ausführungsplans) mit einem indizierten Feld anstelle von * (object_id ist das numerische Feld, auf das in dieser Tabelle häufig Bezug genommen wird). Verwenden Sie type = 'U' anstelle von type in (N'U '). (Die Spalte _type ist vom Typ char, wobei Nchar eine implizite Konvertierung verursacht, die häufig Probleme mit dem Kardinalitätsschätzer verursacht.)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

Nur zum Kontrast verwende ich gerne die Funktion object_id wie unten gezeigt. Es ist etwas einfacher zu lesen und Sie müssen sich keine Gedanken über sys.objects vs. sysobjects vs. sys.all_objects vs. sys.tables machen. Grundform:

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

Dies wird natürlich als " Vorhanden " angezeigt, wenn ein Objekt mit diesem Namen vorhanden ist. Wenn Sie nur Tabellen überprüfen möchten, benötigen Sie:

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

Es funktioniert auch für temporäre Tabellen:

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

2
Normalerweise sehe ich die andere Methode (Überprüfung der Systemtabellen), aber diese scheint lesbar und kompakt zu sein. Gibt es einen Grund, diese Methode der akzeptierten Antwort nicht vorzuziehen? (Wie Kompatibilitätsprobleme mit der SQL-Migration zu verschiedenen DB-Anbietern, Geschwindigkeit usw.)?
jedd.ahyoung

16

Lassen Sie uns eine Beispieldatenbank mit einer Tabelle mit dem folgenden Skript erstellen:

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

Ansatz 1: Verwenden der Ansicht INFORMATION_SCHEMA.TABLES

Wir können eine Abfrage wie unten schreiben, um zu überprüfen, ob eine tblTest-Tabelle in der aktuellen Datenbank vorhanden ist.

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

Die obige Abfrage überprüft das Vorhandensein der Tabelle tblTest in allen Schemas in der aktuellen Datenbank. Wenn Sie stattdessen die Existenz der Tabelle in einem angegebenen Schema und der angegebenen Datenbank überprüfen möchten, können Sie die obige Abfrage wie folgt schreiben:

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

Vorteile dieses Ansatzes: INFORMATION_SCHEMA-Ansichten können auf verschiedene RDBMS-Systeme portiert werden, sodass für die Portierung auf verschiedene RDBMS keine Änderungen erforderlich sind.

Ansatz 2: Verwenden der Funktion OBJECT_ID ()

Wir können die folgende OBJECT_ID()Funktion verwenden, um zu überprüfen, ob eine tblTest-Tabelle in der aktuellen Datenbank vorhanden ist.

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

Das Angeben der Teile Datenbankname und Schemaname für den Tabellennamen ist optional. Die Angabe des Datenbanknamens und des Schemanamens bietet jedoch die Möglichkeit, das Vorhandensein der Tabelle in der angegebenen Datenbank und in einem angegebenen Schema zu überprüfen, anstatt die aktuelle Datenbank in allen Schemas einzuchecken. Die folgende Abfrage zeigt, dass wir, obwohl die aktuelle Datenbank eine MASTER-Datenbank ist, die Existenz der tblTestTabelle im dboSchema in der TestDatenbank überprüfen können .

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

Vorteile: Leicht zu merken. Ein weiterer bemerkenswerter Punkt, der über die OBJECT_ID()Funktion erwähnt werden muss, ist: Sie bietet eine Option zum Überprüfen der Existenz der temporären Tabelle, die im aktuellen Verbindungskontext erstellt wird. Alle anderen Ansätze überprüfen das Vorhandensein der temporären Tabelle, die im gesamten Verbindungskontext und nicht nur im aktuellen Verbindungskontext erstellt wurde. Die folgende Abfrage zeigt, wie Sie das Vorhandensein einer temporären Tabelle mithilfe der OBJECT_ID()Funktion überprüfen können:

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

Ansatz 3: Verwenden der Katalogansicht von sys.Objects

Wir können die Sys.ObjectsKatalogansicht verwenden, um das Vorhandensein der Tabelle wie folgt zu überprüfen:

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

Ansatz 4: Verwenden der Katalogansicht von sys.Tables

Wir können die Sys.TablesKatalogansicht verwenden, um das Vorhandensein der Tabelle wie folgt zu überprüfen:

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

Sys.TablesDie Katalogansicht erbt die Zeilen von der Sys.ObjectsKatalogansicht. Die Sys.objectsKatalogansicht wird als Basisansicht sys.Tablesbezeichnet, während sie als abgeleitete Ansicht bezeichnet wird. Sys.TablesGibt die Zeilen nur für die Tabellenobjekte zurück, während Sys.Objectview neben der Rückgabe der Zeilen für Tabellenobjekte auch Zeilen für die Objekte zurückgibt, z. B.: gespeicherte Prozedur, Ansichten usw.

Ansatz 5: Vermeiden Sie die Verwendung der Systemtabelle sys.sysobjects

Wir sollten vermeiden, sys.sysobjectsdie Systemtabelle direkt zu verwenden. In einigen zukünftigen Versionen des SQL Servers wird der direkte Zugriff darauf veraltet sein. Gemäß dem Link [Microsoft BOL] [1] schlägt Microsoft vor, die Katalogansichten sys.objects/sys.tablesanstelle der sys.sysobjectsSystemtabelle direkt zu verwenden.

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

Referenz: http://sqlhints.com/2014/04/13/how-to-check-if-a-table-exists-in-sql-server/


Es ist wichtig zu beachten, dass diese Antwort angibt, bei welchem ​​Ansatz die Datenbank angegeben werden muss und bei welchem ​​nicht. Dies ist äußerst wertvoll. Für Skripts, die zum Einrichten und Aktualisieren einer Betriebsdatenbank ausgeführt werden, wenn mehrere derselben Datenbank auf derselben Instanz ausgeführt werden, ist dies der Schlüssel! Tolle Informationen.
Nelda.techspiress

11

BEARBEITET

Sie können in sys.tables nachsehen, ob die gewünschte Tabelle vorhanden ist:

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
Willkommen bei StackOverflow. Erwägen Sie bei der Beantwortung von Fragen auch eine Erklärung. Code allein ist die meiste Zeit nicht sehr hilfreich.
Viktor

0

Versuchen Sie die folgende Anweisung, um das Vorhandensein einer Tabelle in der Datenbank zu überprüfen:

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

Sie können die Tabelle im if-Block erstellen.


3
Während diese Syntax funktioniert, sysobjectsgibt es eine Kompatibilitätsansicht, die nur existiert, um zu vermeiden, dass älterer Code beschädigt wird. Mein Vorschlag zur Verwendung Systemkatalogsichten (zB würde sys.objects, sys.tables) für Code, der nur SQL Server 2008 Instanzen Ziel, und Informationsschema Ansichten (zB information_schema.tables) für Code , dass Bedürfnisse tragbar sein. Weitere Informationen zu den verschiedenen Ansichten finden Sie hier: Abfragen des SQL Server-Systemkatalogs
ajk

-2

Wenn ich mich nicht irre, sollte dies funktionieren:

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

2
Was ist, wenn die Tabelle existiert, aber leer ist
?

@SQLMeance Oh ok, ich verstehe aus Ihrer Antwort, dass Sie in sys.objects nach dem Typ 'U' suchen. Können Sie mir helfen, zu verstehen, warum Sie dies empfehlen? und kann eine Tabelle irgendwo anders existieren? Vielen Dank im Voraus
RaM
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.