Controlla se la tabella esiste e se non esiste, creala in SQL Server 2008


130

Sto scrivendo una procedura memorizzata in SQL Server 2008. Devo verificare se esiste una tabella nel database. In caso contrario, devo crearlo.

Come faccio a fare questo?


2
Correlato, se non duplicato: verificare se esiste una tabella in SQL Server .

1
Questa è una grande domanda che alla fine verranno poste da tutti coloro che lavorano con SQL Server. È triste che SQL Server non abbia il simpatico stile Oracle CREATE O REPLACE
Davos

1
Per MySQL puoi usareCREATE TABLE IF NOT EXISTS ...
John Henckel il

Risposte:


148

Qualcosa come questo

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
considera rispettosamente alcune modifiche (per il bene del piano di esecuzione) usando un campo indicizzato invece di * (object_id è il campo numerico comunemente indicato in questa tabella) usa type = 'U' invece di digitare (N'U ') (la colonna _type è di tipo char usando Nchar provoca una conversione implicita che spesso causa problemi con lo stimatore della cardinalità)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

Solo per contrasto, mi piace usare la funzione object_id come mostrato di seguito. È un po 'più facile da leggere e non devi preoccuparti di sys.objects vs. sysobjects vs. sys.all_objects vs. sys.tables. Forma base:

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

Naturalmente questo mostrerà come "Presente" se c'è qualche oggetto presente con quel nome. Se vuoi controllare solo le tabelle, avresti bisogno di:

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

Funziona anche con tabelle temporanee:

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

2
Di solito vedo l'altro metodo usato (controllare le tabelle di sistema) ma questo sembra molto leggibile e compatto. c'è qualche motivo per non preferire questo metodo alla risposta accettata? (Come problemi di compatibilità con la migrazione SQL a diversi provider DB, velocità, ecc.)?
jedd.ahyoung,

16

Creiamo un database di esempio con una tabella con lo script seguente:

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

Approccio 1: utilizzo della vista INFORMATION_SCHEMA.TABLES

Possiamo scrivere una query come sotto per verificare se esiste una tabella tblTest nel database corrente.

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

La query sopra verifica l'esistenza della tabella tblTest in tutti gli schemi nel database corrente. Invece di questo se si desidera verificare l'esistenza della tabella in uno schema specificato e nel database specificato, è possibile scrivere la query sopra come di seguito:

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

Pro di questo approccio: le viste INFORMATION_SCHEMA sono portatili su diversi sistemi RDBMS, quindi il porting su diversi RDBMS non richiede alcuna modifica.

Approccio 2: utilizzo della funzione OBJECT_ID ()

Possiamo usare la OBJECT_ID()funzione come sotto per verificare se esiste una tabella tblTest nel database corrente.

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

La specifica delle parti Nome database e Nome schema per il Nome tabella è facoltativa. Ma la specifica del Nome database e del Nome schema fornisce un'opzione per verificare l'esistenza della tabella nel database specificato e all'interno di uno schema specificato, anziché effettuare il check-in nel database corrente in tutti gli schemi. La query seguente mostra che anche se il database corrente è il database MASTER, possiamo verificare l'esistenza della tblTesttabella nello dboschema nel Testdatabase.

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

Pro: facile da ricordare. Un altro punto degno di nota sulla OBJECT_ID()funzione è: fornisce un'opzione per verificare l'esistenza della tabella temporanea creata nel contesto di connessione corrente. Tutti gli altri approcci verifica l'esistenza della tabella temporanea creata in tutti i contesti di connessione anziché solo nel contesto di connessione corrente. La query di seguito mostra come verificare l'esistenza di una tabella temporanea utilizzando la OBJECT_ID()funzione:

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

Approccio 3: utilizzo di sys.Objects Catalog View

Possiamo usare la Sys.Objectsvista del catalogo per verificare l'esistenza della tabella come mostrato di seguito:

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

Approccio 4: utilizzo di sys.Tables Visualizzazione catalogo

Possiamo usare la Sys.Tablesvista del catalogo per verificare l'esistenza della tabella come mostrato di seguito:

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

Sys.Tablesla vista del catalogo eredita le righe dalla Sys.Objectsvista del catalogo, la vista del Sys.objectscatalogo viene definita vista di base dove sys.Tablesviene definita vista derivata. Sys.Tablesrestituirà le righe solo per gli oggetti Table mentre Sys.Objectview oltre a restituire le righe per gli oggetti table, restituisce righe per gli oggetti come: stored procedure, viste ecc.

Approccio 5: evitare l'uso della tabella di sistema sys.sysobjects

Dovremmo evitare di usare sys.sysobjectsdirettamente la tabella di sistema, l'accesso diretto ad esso sarà deprecato in alcune versioni future del server SQL. Secondo il link [Microsoft BOL] [1], Microsoft suggerisce di utilizzare direttamente le viste del catalogo sys.objects/sys.tablesanziché la sys.sysobjectstabella di sistema.

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

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


È importante notare che questa risposta fornisce quale approccio necessita di specificare il database e quali no. Questo è estremamente utile e per gli script eseguiti per configurare e aggiornare un database operativo quando sono presenti più dello stesso database in esecuzione nella stessa istanza, questa è la chiave! Ottima informazione
Nelda.techspiress,

11

MODIFICATO

Puoi guardare in sys.tables per verificare la tabella di esistenza desiderata:

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
Benvenuto in StackOverflow. Quando rispondi alle domande, considera di aggiungere anche una spiegazione. Il codice da solo non è molto utile per la maggior parte del tempo.
Viktor,

0

Prova la seguente dichiarazione per verificare l'esistenza di una tabella nel database:

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

È possibile creare la tabella all'interno del blocco if.


3
Mentre quella sintassi funzionerà, sysobjectsè una vista di compatibilità che esiste solo per evitare di rompere il codice più vecchio. Il mio suggerimento sarebbe di utilizzare le viste del catalogo di sistema (ad es sys.objects. sys.tables) Per il codice destinato esclusivamente alle istanze di SQL Server 2008 e le viste dello schema di informazioni (ad es. information_schema.tables) Per il codice che deve essere portatile. Puoi trovare ulteriori informazioni sulle diverse visualizzazioni qui: Richiesta del catalogo di sistema di SQL Server
ajk

-2

Se non sbaglio, dovrebbe funzionare:

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

2
cosa succede se la tabella esiste ma è vuota, questo sarà vero in quel caso
SQLMenace,

@SQLMeance Oh ok, ho capito dalla tua risposta che stai controllando il tipo 'U' in sys.objects, Potresti aiutarmi a capire, perché mi raccomandi? e può esistere un tavolo altrove? Grazie in anticipo
RaM,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.