Wie überprüfe ich, ob eine Spalte in einer SQL Server-Tabelle vorhanden ist?

1853

Ich muss eine bestimmte Spalte hinzufügen, wenn sie nicht vorhanden ist. Ich habe so etwas wie das Folgende, aber es gibt immer false zurück:

IF EXISTS(SELECT *
          FROM   INFORMATION_SCHEMA.COLUMNS
          WHERE  TABLE_NAME = 'myTableName'
                 AND COLUMN_NAME = 'myColumnName') 

Wie kann ich überprüfen, ob eine Spalte in einer Tabelle der SQL Server-Datenbank vorhanden ist?

Maciej
quelle
12
Ich glaube nicht, dass irgendetwas mit dem Code in der Frage falsch ist: Funktioniert gut für mich in 2008 R2. (Vielleicht haben Sie es in der falschen Datenbank ausgeführt? Vielleicht hat Ihre Datenbank zwischen Groß- und Kleinschreibung unterschieden und Sie hatten in Ihren Zeichenfolgen myTableName / myColumnName nicht die richtige Groß- und Kleinschreibung? Diese Art von Abfrage scheint flexibler zu sein als die COL_LENGTH-Lösung: Ich bin in der Lage um es gegen eine andere Datenbank und sogar über eine Datenbankverbindung auszuführen, indem "INFORMATION_SCHEMA" entsprechend vorangestellt wird. Ich konnte nicht sehen, wie das mit der Metadatenfunktion COL_LENGTH gemacht werden soll.
mwardm
3
@mwardm - COL_LENGTH('AdventureWorks2012.HumanResources.Department ','ModifiedDate')funktioniert gut.
Martin Smith
6
Kleiner verwandter Hinweis: Wenn Sie eine Spalte direkt nach dem Hinzufügen der Spalte aktualisieren möchten (ich glaube, viele Benutzer haben diesen Artikel zu diesem Zweck durchsucht), können Sie ihn EXEC sp_executesqlmit einer formulierten UPDATEAnweisung verwenden.
Cassandrad
Die wirkliche Antwort ist, dass Sie die Datenbank hinzufügen sollten, gegen die Sie prüfen, damit es istFROM [YourDatabase].INFORMATION_SCHEMA.COLUMNS
Alex Kwitny

Antworten:

2054

Ab SQL Server 2005:

IF EXISTS(SELECT 1 FROM sys.columns 
          WHERE Name = N'columnName'
          AND Object_ID = Object_ID(N'schemaName.tableName'))
BEGIN
    -- Column Exists
END

Martin Smiths Version ist kürzer:

IF COL_LENGTH('schemaName.tableName', 'columnName') IS NOT NULL
BEGIN
    -- Column Exists
END
Mitch Wheat
quelle
In der Version von Martin Smith ist zu erwähnen, dass columnName nicht in eckige Klammern [] gesetzt wird. Wenn sich columnName in eckigen Klammern [] befindet, wird null
ausgegeben,
@HemendraSinghChauhan - das liegt daran, dass sie nicht Teil des Namens sind. Sie werden auch feststellen, dass beim Vergleich mit dem Namen insys.columns
Martin Smith
@MartinSmith wusste das nicht, ich habe Ihre Antwort verwendet und bin darauf gestoßen. Im Allgemeinen verwende ich beim Hinzufügen von Spalten eckige Klammern, daher habe ich sie auch in der Funktion COL_LENGTH verwendet. Mein Code war wie Alter table Table_Name Add [ColumnName] NVarchar(max) NULL; Select COL_LENGTH('[TABLE_NAME]', '[COLUMN_NAME]')
folgt
ja das ist nicht gültig Die Argumente COL_LENGTHmüssen nicht zitiert werden. Es ist theoretisch möglich, dass jemand eine Spalte erstellt, die tatsächlich den Namen hat [COLUMN_NAME]- z. B. CREATE TABLE #T([[COLUMN_NAME]]] INT); SELECT * FROM #Tund dann wäre es mehrdeutig, wenn dies nicht die Regel wäre.
Martin Smith
987

Eine prägnantere Version

IF COL_LENGTH('table_name','column_name') IS NULL
BEGIN
/* Column does not exist or caller does not have permission to view the object */
END

Der Punkt über Berechtigungen zum Anzeigen von Metadaten gilt für alle Antworten, nicht nur für diese.

Beachten Sie, dass der erste Name der Parametertabelle je nach COL_LENGTHBedarf in einem, zwei oder drei Teilenamen vorliegen kann.

Ein Beispiel für die Referenzierung einer Tabelle in einer anderen Datenbank ist

COL_LENGTH('AdventureWorks2012.HumanResources.Department','ModifiedDate')

Ein Unterschied zu dieser Antwort im Vergleich zur Verwendung der Metadatenansichten besteht darin, dass Metadatenfunktionen, wie z. B. COL_LENGTHimmer nur Daten zu festgeschriebenen Änderungen zurückgeben, unabhängig von der geltenden Isolationsstufe.

Martin Smith
quelle
11
Dies ist weniger lesbar als einige der anderen Antworten, wahrscheinlich, warum es nicht so hoch bewertet wird.
Bill Yang
38
@ Bill - Auf welche Weise weniger lesbar? Sieht in Firefox gut aus. Diese Antwort wurde mehr als 2 Jahre später als die akzeptierte veröffentlicht, was die Bewertung IMO erklärt. Wenn Sie weniger klar gemeint haben, dass es sich um eine Existenz handelt, überprüfen Sie, ob diese Art von Redewendung in SQL Server weit verbreitet ist. zB verwenden IF OBJECT_ID('TableName','U') IS NULL, um die Existenz von Objekten oder die Existenz DB_ID('foo')von Datenbanken zu überprüfen.
Martin Smith
59
@MartinSmith Ich bin sicher, er meinte weniger lesbar, denn wenn Sie diese Redewendung nicht kennen und diesen Code von jemand anderem geerbt haben, würden Sie nicht sofort verstehen, was der Code tut. Ein bisschen wie Schreiben x>>2statt x/4in C ++. Der ausführlichere Code ( if exists (select column_name from information_schema ...)) nimmt viel mehr Platz ein, aber niemand würde sich jemals am Kopf kratzen, um herauszufinden, was er tut.
Kip
22
Neben einer präziseren Lösung ist dies eine viel schnellere Lösung. Zugriff auf INFORMATION_SCHEMAAnsichten oder sys.columnsTreffer auf der Festplatte, während COL_LENGTHzwischengespeicherte Datenbankmetadaten verwendet werden.
wqw
7
Dies ist wahrscheinlich nicht die am höchsten bewertete Antwort, da sie 2,5 Jahre nach der anderen gegeben wurde. Deshalb überprüfe ich immer die Daten, wenn ich die Bewertungen für zwei Antworten vergleiche. Es dauert viel länger, eine Antwort zu überwinden, die viel früher gegeben wurde. ;)
Sean
149

Passen Sie das Folgende an Ihre spezifischen Anforderungen an:

if not exists (select
                     column_name
               from
                     INFORMATION_SCHEMA.columns
               where
                     table_name = 'MyTable'
                     and column_name = 'MyColumn')
    alter table MyTable add MyColumn int

Bearbeiten, um sich mit Bearbeiten zu befassen, um zu fragen : Das sollte funktionieren - überprüfen Sie Ihren Code sorgfältig auf dumme Fehler; Fragen Sie beispielsweise INFORMATION_SCHEMA in derselben Datenbank ab, auf die Ihre Einfügung angewendet wird? Haben Sie in beiden Anweisungen einen Tippfehler in Ihrem Tabellen- / Spaltennamen?

Luke Bennett
quelle
3
Ich habe gerade herausgefunden, dass das Hinzufügen von TABLE_SCHEMA = 'mySchema' nach der where-Klausel das Problem behebt.
Maciej
12
-1: Beantwortet die Frage von OP nicht, fügt nur die neuen Informationen zum Hinzufügen einer neuen Spalte hinzu, obwohl OP überhaupt nicht danach fragt, und geht nicht auf den Kommentar von OP ein.
ANeves
1
+1 Beantwortet die Frage von OP perfekt mit einem Bonus der zusätzlichen Informationen, die das OP sowieso als nächstes anstrebt. Und das war es, wonach ich gesucht habe.
Bitterblue
74

Versuche dies...

IF NOT EXISTS(
  SELECT TOP 1 1
  FROM INFORMATION_SCHEMA.COLUMNS
  WHERE 
    [TABLE_NAME] = 'Employees'
    AND [COLUMN_NAME] = 'EmployeeID')
BEGIN
  ALTER TABLE [Employees]
    ADD [EmployeeID] INT NULL
END
Leon Tayson
quelle
6
Diese Methode funktioniert auch mit SQL CE, während einige der anderen genannten Methoden dies nicht tun.
SWalters - Wiedereinsetzung Monica
9
Sie können SELECT 1anstelle von SELECT TOP 1 1;) verwenden.
shA.t
4
Innerhalb einer EXISTSAnweisung optimiert SQL die Spalten automatisch (ähnlich wie count(*)), sodass dies SELECT *ausreicht.
Marc L.
Der Vollständigkeit halber sollten Sie and [TABLE_SCHEMA] = '???'die WHERE-Klausel ergänzen .
Andrew Jens
50

Für die Personen, die die Existenz der Spalte überprüfen, um sie zu löschen.

Ab SQL Server 2016 können Sie anstelle großer IFWrapper neue DIE-Anweisungen verwenden

ALTER TABLE Table_name DROP COLUMN IF EXISTS Column_name
P ரதீப்
quelle
47

Ich würde INFORMATION_SCHEMA.COLUMNSeine Systemtabelle vorziehen , da Microsoft nicht garantiert, dass die Systemtabellen zwischen den Versionen erhalten bleiben. Funktioniert beispielsweise dbo.syscolumnsimmer noch in SQL 2008, ist jedoch veraltet und kann in Zukunft jederzeit entfernt werden.

Christian Hayter
quelle
5
Ja, das versteht sich von selbst, da INFORMATION_SCHEMAAnsichten nur ANSI-Standard-Metadaten enthalten. Dies reicht jedoch für einen Existenztest aus.
Christian Hayter
3
Microsoft sagt: "In zukünftigen Versionen von SQL Server kann Microsoft die Definition jeder Systemkatalogansicht erweitern, indem Spalten am Ende der Spaltenliste hinzugefügt werden. Wir empfehlen, die Syntax SELECT * FROM sys.catalog_view_name nicht im Produktionscode zu verwenden, da die Anzahl von Die zurückgegebenen Spalten können sich ändern und Ihre Anwendung beschädigen. " Das bedeutet, dass sie keine Spalten entfernen oder ihre Reihenfolge ändern. Das ist gut genug Abwärtskompatibilität für alle außer Randfällen.
Siride
42

Sie können die Systemansichten des Informationsschemas verwenden, um so ziemlich alles über die Tabellen herauszufinden, an denen Sie interessiert sind:

SELECT *
  FROM INFORMATION_SCHEMA.COLUMNS
 WHERE TABLE_NAME = 'yourTableName'
 ORDER BY ORDINAL_POSITION

Mit den Ansichten Information_schema können Sie auch Ansichten, gespeicherte Prozeduren und so ziemlich alles über die Datenbank abfragen.

anonym
quelle
Genau das verwendet der Fragebogen. Er musste wissen, wie man die Spalte hinzufügt, wenn sie nicht existiert.
Birel
35

Versuchen Sie etwas wie:

CREATE FUNCTION ColumnExists(@TableName varchar(100), @ColumnName varchar(100))
RETURNS varchar(1) AS
BEGIN
DECLARE @Result varchar(1);
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = @TableName AND COLUMN_NAME = @ColumnName)
BEGIN
    SET @Result = 'T'
END
ELSE
BEGIN
    SET @Result = 'F'
END
RETURN @Result;
END
GO

GRANT EXECUTE ON  [ColumnExists] TO [whoever]
GO

Dann benutze es so:

IF ColumnExists('xxx', 'yyyy') = 'F'
BEGIN
  ALTER TABLE xxx
  ADD yyyyy varChar(10) NOT NULL
END
GO

Es sollte sowohl unter SQL Server 2000 als auch unter SQL Server 2005 funktionieren. Ich bin mir bei SQL Server 2008 nicht sicher, verstehe aber nicht, warum nicht.

Matt Lacey
quelle
34

Überprüfen Sie zunächst, ob die Kombination table/ column( id/ name) in dbo.syscolumns(einer internen SQL Server-Tabelle, die Felddefinitionen enthält) vorhanden ist, und geben Sie gegebenenfalls die entsprechende ALTER TABLEAbfrage aus, um sie hinzuzufügen. Zum Beispiel:

IF NOT EXISTS ( SELECT  *
            FROM    syscolumns
            WHERE   id = OBJECT_ID('Client')
                    AND name = 'Name' ) 
ALTER TABLE Client
ADD Name VARCHAR(64) NULL
mdb
quelle
28

Ein guter Freund und Kollege von mir hat mir gezeigt, wie Sie auch einen IFBlock mit SQL-Funktionen OBJECT_IDund COLUMNPROPERTYin SQL SERVER 2005+ verwenden können, um nach einer Spalte zu suchen. Sie können Folgendes verwenden:

Hier können Sie sich selbst davon überzeugen

IF (OBJECT_ID(N'[dbo].[myTable]') IS NOT NULL AND
    COLUMNPROPERTY( OBJECT_ID(N'[dbo].[myTable]'), 'ThisColumnDoesNotExist', 'ColumnId') IS NULL)
BEGIN
    SELECT 'Column does not exist -- You can add TSQL to add the column here'
END
brasilianldsjaguar
quelle
1
Und wenn Sie sicher sind, dass die Tabelle vorhanden ist, können Sie natürlich den ersten Teil der Bedingung weglassen und COLUMNPROPERTYnur aktivieren .
Ruud Helderman
26
declare @myColumn   as nvarchar(128)
set @myColumn = 'myColumn'
if not exists (
    select  1
    from    information_schema.columns columns 
    where   columns.table_catalog   = 'myDatabase'
        and columns.table_schema    = 'mySchema' 
        and columns.table_name      = 'myTable' 
        and columns.column_name     = @myColumn
    )
begin
    exec('alter table myDatabase.mySchema.myTable add'
    +'    ['+@myColumn+'] bigint       null')
end
Tuomo Kämäräinen
quelle
22

Dies hat bei mir in SQL 2000 funktioniert:

IF EXISTS 
(
    SELECT * 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE table_name = 'table_name' 
    AND column_name = 'column_name'
)
BEGIN
...
END
Joe M.
quelle
21

Versuche dies

SELECT COLUMNS.*
FROM   INFORMATION_SCHEMA.COLUMNS COLUMNS,
       INFORMATION_SCHEMA.TABLES TABLES
WHERE  COLUMNS.TABLE_NAME = TABLES.TABLE_NAME
       AND Upper(COLUMNS.COLUMN_NAME) = Upper('column_name') 
Douglas Tondo
quelle
Sie brauchen keine INFORMATION_SCHEMA.TABLESSpalten für eine bestimmte Tabelle und filtern sie auch nicht. Daher wird manchmal mehr als eine Zeile für dieselben Spaltennamen in separaten Tabellen zurückgegeben;).
shA.t
19

Ich brauchte ähnliche für SQL SERVER 2000 und, wie @Mitch betont, funktioniert dies nur in 2005+.

Sollte es jemand anderem helfen, hat dies am Ende für mich funktioniert:

if exists (
    select * 
    from 
        sysobjects, syscolumns 
    where 
        sysobjects.id = syscolumns.id 
        and sysobjects.name = 'table' 
        and syscolumns.name = 'column')
ErfrierungenXIII
quelle
15
if exists (
  select * 
  from INFORMATION_SCHEMA.COLUMNS 
  where TABLE_NAME = '<table_name>' 
  and COLUMN_NAME = '<column_name>'
) begin
  print 'Column you have specified exists'
end else begin
  print 'Column does not exist'
end
BYRAKUR SURESH BABU
quelle
13
IF NOT EXISTS( SELECT NULL
            FROM INFORMATION_SCHEMA.COLUMNS
           WHERE table_name = 'TableName'
             AND table_schema = 'SchemaName'
             AND column_name = 'ColumnName')  BEGIN

  ALTER TABLE [SchemaName].[TableName] ADD [ColumnName] int(1) NOT NULL default '0';

END;
Na30m
quelle
2
Ich denke du meintest table_schema = 'schema_name'.
Tab Alleman
11

Eine temporäre Tabellenversion der akzeptierten Antwort :

if (exists(select 1 
             from tempdb.sys.columns  
            where Name = 'columnName'
              and Object_ID = object_id('tempdb..#tableName')))
begin
...
end
crokusek
quelle
1
Wie unterscheidet sich das von der akzeptierten Antwort? Würde eine temporäre Tabelle in der akzeptierten Antwort nicht funktionieren?
John Saunders
1
Richtig. Die akzeptierte Antwort funktioniert nicht für temporäre Tabellen, da 'sys.columns' als 'tempdb.sys.columns' angegeben werden muss und dem Tabellennamen 'tempdb ..' vorangestellt werden muss.
Crokusek
10
select distinct object_name(sc.id)
from syscolumns sc,sysobjects so  
where sc.name like '%col_name%' and so.type='U'
Nishad
quelle
8

Die Antwort von Wheat ist gut, setzt jedoch voraus, dass Sie in keinem Schema oder in keiner Datenbank identische Paare aus Tabellenname und Spaltenname haben. Um es für diesen Zustand sicher zu machen, verwenden Sie dieses ...

select *
from Information_Schema.Columns
where Table_Catalog = 'DatabaseName'
  and Table_Schema = 'SchemaName'
  and Table_Name = 'TableName'
  and Column_Name = 'ColumnName'
Daniel Barbalace
quelle
8

Es gibt verschiedene Möglichkeiten, das Vorhandensein einer Spalte zu überprüfen. Ich würde dringend empfehlen, es so zu verwenden, INFORMATION_SCHEMA.COLUMNSwie es erstellt wurde, um mit dem Benutzer zu kommunizieren. Betrachten Sie folgende Tabellen:

 sys.objects
 sys.columns

und sogar einige andere verfügbare Zugriffsmethoden zur Überprüfung system catalog.

Auch keine Notwendigkeit zu verwenden SELECT *, testen Sie es einfach durchNULL value

IF EXISTS(
           SELECT NULL 
           FROM INFORMATION_SCHEMA.COLUMNS
           WHERE
             TABLE_NAME = 'myTableName'
             AND COLUMN_NAME = 'myColumnName'
         ) 
Ali Elmi
quelle
1
Egal, ob Sie SELECT *mit EXISTS, denn wenn vorhanden verwendet wird, werden nicht wirklich alle Zeilen und Spalten ausgewählt. Intern wird nur die Existenz und nicht alle Zeilen und Spalten überprüft
Pawan Nogariya
7

Eine der einfachsten und verständlichsten Lösungen ist:

IF COL_LENGTH('Table_Name','Column_Name') IS NULL
 BEGIN
    -- Column Not Exists, implement your logic
 END 
ELSE
 BEGIN
    -- Column Exists, implement your logic
 END
Arsman Ahmad
quelle
7

Hier ist ein einfaches Skript, mit dem ich das Hinzufügen von Spalten in der Datenbank verwalte:

IF NOT EXISTS (
        SELECT *
        FROM sys.Columns
        WHERE Name = N'QbId'
            AND Object_Id = Object_Id(N'Driver')
        )
BEGIN
    ALTER TABLE Driver ADD QbId NVARCHAR(20) NULL
END
ELSE
BEGIN
    PRINT 'QbId is already added on Driver'
END

In diesem Beispiel Nameist das ColumnNamedas hinzuzufügende und Object_Iddas dasTableName

UJS
quelle
4

Die folgende Abfrage kann verwendet werden, um zu überprüfen, ob die gesuchte Spalte in der Tabelle vorhanden ist oder nicht. Wir können die Entscheidung basierend auf dem gesuchten Ergebnis auch wie unten gezeigt treffen.

IF EXISTS (SELECT 'Y' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = <YourTableName> AND COLUMN_NAME = <YourColumnName>)
  BEGIN
    SELECT 'Column Already Exists.'
  END
  ELSE
  BEGIN
    ALTER TABLE <YourTableName> ADD <YourColumnName> <DataType>[Size]
  END
Suraj Kumar
quelle
3

Noch eine Variation ...

SELECT 
  Count(*) AS existFlag 
FROM 
  sys.columns 
WHERE 
  [name] = N 'ColumnName' 
  AND [object_id] = OBJECT_ID(N 'TableName')
Manuel Alves
quelle
1

Tabelle -> Skript Tabelle als -> neue Fenster - Sie haben Design-Skript. Überprüfen und finden Sie den Spaltennamen in neuen Fenstern

Arnav
quelle
1

Führen Sie die folgende Abfrage aus, um zu überprüfen, ob die Spalte in der angegebenen Tabelle vorhanden ist:

IF(SELECT COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'TableName' AND COLUMN_NAME = 'ColumnName') IS NOT NULL
PRINT 'Column Exists in the given table';
S Krishna
quelle
1

Ein weiterer Beitrag ist das folgende Beispiel, in dem die Spalte hinzugefügt wird, falls sie nicht vorhanden ist.

    USE [Northwind]
    GO

    IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS 
                    WHERE TABLE_NAME = 'Categories'
                        AND COLUMN_NAME = 'Note')
    BEGIN

    ALTER TABLE Categories ADD Note NVARCHAR(800) NULL

    END
    GO

Ich hoffe es hilft. Simone

Simone Spagna
quelle
0
IF EXISTS(SELECT 1 FROM sys.columns 
      WHERE Name = N'columnName'
      AND Object_ID = Object_ID(N'schemaName.tableName'))

Dies sollte der ziemlich einfachere Weg und eine einfache Lösung für dieses Problem sein. Ich habe dies mehrfach für ähnliche Szenarien verwendet. Es funktioniert wie ein Zauber, daran gibt es keine Zweifel.

Ilangeeran
quelle
0
IF EXISTS (
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_CATALOG = 'Database Name'
and TABLE_SCHEMA = 'Schema Name'
and TABLE_NAME = 'Table Name'
and COLUMN_NAME = 'Column Name'
and DATA_TYPE = 'Column Type') -- Where statement lines can be deleted.

BEGIN
--COLUMN EXISTS IN TABLE
END

ELSE BEGIN
--COLUMN DOES NOT EXISTS IN TABLE
END
Mohamad Reza Shahrestani
quelle
0

Tun Sie etwas, wenn keine Spalte vorhanden ist:

BEGIN
    IF (COL_LENGTH('[dbo].[Table]', 'Column ') IS NULL)
    BEGIN
        //Do something
    END
END;

Tun Sie etwas, wenn eine Spalte vorhanden ist:

BEGIN
    IF (COL_LENGTH('[dbo].[Table]', 'Column ') IS NOT NULL)
    BEGIN
        //Do something
    END
END;
Jagjit Singh
quelle