Jak sprawdzić, czy kolumna istnieje w tabeli programu SQL Server?

1853

Muszę dodać konkretną kolumnę, jeśli nie istnieje. Mam coś takiego, ale zawsze zwraca false:

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

Jak mogę sprawdzić, czy kolumna istnieje w tabeli bazy danych SQL Server?

Maciej
źródło
12
Nie sądzę, żeby coś było nie tak z kodem w pytaniu: Działa dla mnie dobrze w 2008 R2. (Być może uruchomiłeś go w niewłaściwej bazie danych? Może w bazie danych rozróżniana jest wielkość liter i nie masz prawidłowej wielkości liter w ciągach myTableName / myColumnName? Ten typ zapytania wydaje się bardziej elastyczny niż rozwiązanie COL_LENGTH: jestem w stanie aby uruchomić go na innej bazie danych, a nawet na łączu bazy danych, odpowiednio poprzedzając przedrostek „INFORMACJE_SCHEMA”. Nie mogłem zobaczyć, jak to zrobić za pomocą funkcji metadanych COL_LENGTH.
mwardm
3
@mwardm - COL_LENGTH('AdventureWorks2012.HumanResources.Department ','ModifiedDate')działa dobrze.
Martin Smith
6
Mała powiązana wskazówka: jeśli chcesz zaktualizować kolumnę zaraz po dodaniu kolumny (uważam, że wielu użytkowników szukało tego artykułu w tym celu), możesz użyć EXEC sp_executesqlsformatowanej UPDATEinstrukcji.
cassandrad
Prawdziwa odpowiedź brzmi: należy dodać bazę danych, z którą sprawdzasz, więc jest toFROM [YourDatabase].INFORMATION_SCHEMA.COLUMNS
Alex Kwitny

Odpowiedzi:

2054

SQL Server 2005 i nowsze:

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

Wersja Martina Smitha jest krótsza:

IF COL_LENGTH('schemaName.tableName', 'columnName') IS NOT NULL
BEGIN
    -- Column Exists
END
Mitch Pszenica
źródło
W wersji Martina Smitha jedną rzeczą, o której należy wspomnieć, nie jest umieszczanie kolumny nazwa_w nawiasach kwadratowych []. Gdy columnName jest w kwadratowych nawiasach [] To da NULL, nawet jeśli istnieje kolumna w tabeli
Hemendra
@HemendraSinghChauhan - to dlatego, że nie są częścią nazwy. Przekonasz się również, że porównując z nazwą wsys.columns
Martin Smith
@MartinSmith nie wiedział o tym, użyłem twojej odpowiedzi i natknąłem się na to. Zasadniczo używam nawiasów kwadratowych podczas dodawania kolumn, więc użyłem ich również w funkcji COL_LENGTH. Mój kod był taki:Alter table Table_Name Add [ColumnName] NVarchar(max) NULL; Select COL_LENGTH('[TABLE_NAME]', '[COLUMN_NAME]')
Hemendra
tak, to nie jest poprawne. Argumentów, które COL_LENGTHnależy przytoczyć. Jest teoretycznie możliwe, że ktoś utworzy kolumnę, która faktycznie ma nazwę [COLUMN_NAME]- np. CREATE TABLE #T([[COLUMN_NAME]]] INT); SELECT * FROM #TI wtedy byłoby niejednoznaczne, gdyby nie była to reguła.
Martin Smith
987

Bardziej zwięzła wersja

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

Punkt dotyczący uprawnień do wyświetlania metadanych dotyczy wszystkich odpowiedzi, nie tylko tej.

Zauważ, że nazwa pierwszej tabeli parametrów COL_LENGTHmoże mieć format jednej, dwóch lub trzech nazw części, zależnie od potrzeb.

Przykładem odniesienia do tabeli w innej bazie danych jest

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

Jedną różnicą w porównaniu z tą odpowiedzią w porównaniu do korzystania z widoków metadanych jest to, że funkcje metadanych, takie jak COL_LENGTHzawsze, zwracają tylko dane o zatwierdzonych zmianach, niezależnie od obowiązującego poziomu izolacji.

Martin Smith
źródło
11
Jest to mniej czytelne niż niektóre inne odpowiedzi, prawdopodobnie dlatego nie jest tak wysoko oceniane.
Bill Yang
38
@Bill - w jaki sposób mniej czytelny? Wygląda dobrze w przeglądarce Firefox. Ta odpowiedź została opublikowana ponad 2 lata później niż odpowiedź zaakceptowana, co tłumaczy ocenę IMO. Jeśli masz na myśli mniej jasne, że jest to sprawdzanie istnienia, ten typ idiomu jest dość powszechny w SQL Server. np. za pomocą IF OBJECT_ID('TableName','U') IS NULLdo sprawdzenia istnienia obiektu lub DB_ID('foo')do sprawdzenia istnienia bazy danych.
Martin Smith
59
@MartinSmith Jestem pewien, że miał na myśli mniej czytelny, ponieważ jeśli nie znasz tego idiomu i odziedziczyłeś ten kod od innej osoby, nie od razu zrozumiałbyś, co robi kod. Coś jak pisanie x>>2zamiast x/4w C ++. Bardziej szczegółowy kod ( if exists (select column_name from information_schema ...)) zajmuje dużo więcej miejsca, ale nikt nigdy nie podrapałby się po głowie, próbując dowiedzieć się, co on robi.
Kip,
22
Poza tym bardziej zwięzłe, jest to znacznie szybsze rozwiązanie. Uzyskiwanie dostępu do INFORMATION_SCHEMAwidoków lub sys.columnstrafień na dysk, przy COL_LENGTHużyciu buforowanych metadanych bazy danych.
wqw
7
To prawdopodobnie nie jest najwyżej oceniana odpowiedź, ponieważ została udzielona 2,5 roku po drugiej. Dlatego zawsze sprawdzam daty, porównując oceny dwóch odpowiedzi. Odpowiedź na pytanie, która została udzielona znacznie wcześniej, zajmuje dużo więcej czasu. ;)
Sean
149

Dostosuj poniżej, aby dopasować do konkretnych wymagań:

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

Edytuj, aby poradzić sobie z edycją na pytanie : To powinno zadziałać - uważnie przejrzyj kod pod kątem głupich błędów; czy pytasz na przykład INFORMACJE_SCHEMA w tej samej bazie danych, do której przykładowo stosuje się twoją wstawkę? Czy masz literówkę w nazwie tabeli / kolumny w dowolnej instrukcji?

Luke Bennett
źródło
3
Właśnie dowiedziałem się, że dodanie TABLE_SCHEMA = „mySchema” po klauzuli gdzie rozwiązuje problem.
Maciej
12
-1: nie odpowiada na pytanie OP, dodaje tylko nowe informacje o tym, jak dodać nową kolumnę, mimo że OP w ogóle o to nie pyta, nie odpowiada na komentarz OP.
ANeves
1
+1 doskonale odpowiada na pytanie OP z premią za dodatkowe informacje, na które OP zamierzał się wybrać. I tego właśnie szukałem.
Bitterblue,
74

Spróbuj tego...

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
źródło
6
Ta metoda działa również z SQL CE, podczas gdy niektóre inne wymienione metody nie.
SWalters - Przywróć Monikę
9
Możesz użyć SELECT 1zamiast SELECT TOP 1 1;).
shA.t
4
W EXISTSinstrukcji SQL automatycznie optymalizuje kolumny (podobnie jak count(*)), więc SELECT *wystarczy.
Marc L.
Ze względu na kompletność należy rozważyć dodanie and [TABLE_SCHEMA] = '???'do klauzuli WHERE.
Andrew Jens,
50

Dla osób, które sprawdzają istnienie kolumny, aby ją upuścić.

Z SQL Server 2016 można używać nowych instrukcji DIE zamiast dużych IFopakowań

ALTER TABLE Table_name DROP COLUMN IF EXISTS Column_name
P ரதீப்
źródło
47

Wolę INFORMATION_SCHEMA.COLUMNStabelę systemową, ponieważ Microsoft nie gwarantuje zachowania tabel systemowych między wersjami. Na przykład dbo.syscolumnsnadal działa w SQL 2008, ale jest przestarzały i może zostać usunięty w dowolnym momencie w przyszłości.

Christian Hayter
źródło
5
Cóż, tak, to oczywiste, ponieważ INFORMATION_SCHEMAwidoki zawierają tylko metadane w standardzie ANSI. To jednak wystarcza do testu istnienia.
Christian Hayter
3
Microsoft mówi „W przyszłych wersjach SQL Server Microsoft może rozszerzyć definicję dowolnego widoku katalogu systemowego, dodając kolumny na końcu listy kolumn. Odradzamy stosowanie składni SELECT * FROM sys.catalog_view_name w kodzie produkcyjnym, ponieważ liczba zwrócone kolumny mogą ulec zmianie i uszkodzić aplikację. ” Oznacza to, że nie usuwają kolumn ani nie zmieniają swojej kolejności. To wystarczająco dobra kompatybilność wsteczna dla wszystkich przypadków oprócz krawędzi.
siride
42

Możesz użyć widoków systemu schematu informacji, aby dowiedzieć się prawie wszystkiego o tabelach, które Cię interesują:

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

Możesz także przesłuchiwać widoki, procedury składowane i prawie wszystko na temat bazy danych, korzystając z widoków Information_schema.

anonimowy
źródło
Właśnie tego używa kwestionariusz, musiał wiedzieć, jak dodać kolumnę, jeśli nie istnieje.
Birel
35

Wypróbuj coś takiego:

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

Następnie użyj go w następujący sposób:

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

Powinien działać zarówno w SQL Server 2000, jak i SQL Server 2005. Nie jestem pewien co do SQL Server 2008, ale nie wiem dlaczego.

Matt Lacey
źródło
34

Najpierw sprawdź, czy istnieje kombinacja table/ column( id/ name) dbo.syscolumns(wewnętrzna tabela programu SQL Server zawierająca definicje pól), a jeśli nie, ALTER TABLEwprowadź odpowiednie zapytanie, aby je dodać. Na przykład:

IF NOT EXISTS ( SELECT  *
            FROM    syscolumns
            WHERE   id = OBJECT_ID('Client')
                    AND name = 'Name' ) 
ALTER TABLE Client
ADD Name VARCHAR(64) NULL
mdb
źródło
28

Mój dobry przyjaciel i mój kolega pokazali mi, jak można również użyć IFbloku z funkcjami SQL OBJECT_IDoraz COLUMNPROPERTYw SQL SERVER 2005+, aby sprawdzić kolumnę. Możesz użyć czegoś podobnego do następującego:

Tutaj możesz się przekonać

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
brazilianldsjaguar
źródło
1
I oczywiście, jeśli masz pewność, że tabela istnieje, możesz pominąć pierwszą część warunku i sprawdzić COLUMNPROPERTYtylko.
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
źródło
22

To działało dla mnie w SQL 2000:

IF EXISTS 
(
    SELECT * 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE table_name = 'table_name' 
    AND column_name = 'column_name'
)
BEGIN
...
END
Joe M.
źródło
21

Spróbuj tego

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
źródło
Nie potrzebujesz INFORMATION_SCHEMA.TABLESi nie filtrujesz kolumn dla określonej tabeli, więc czasami zwraca więcej niż jeden wiersz dla tych samych nazw kolumn w osobnych tabelach;).
ShA.t
19

Potrzebowałem podobnych dla SQL SERVER 2000 i, jak wskazuje @Mitch, działa to tylko w wersji 2005+.

Jeśli powinno to pomóc komukolwiek innemu, to w końcu zadziałało dla mnie:

if exists (
    select * 
    from 
        sysobjects, syscolumns 
    where 
        sysobjects.id = syscolumns.id 
        and sysobjects.name = 'table' 
        and syscolumns.name = 'column')
Odmrożenie XIII
źródło
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
źródło
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
źródło
2
Myślę, że miałeś na myśli table_schema = 'nazwa schematu'.
Tab Alleman
11

Wersja akceptowanej tabeli tymczasowej :

if (exists(select 1 
             from tempdb.sys.columns  
            where Name = 'columnName'
              and Object_ID = object_id('tempdb..#tableName')))
begin
...
end
Crokusek
źródło
1
Czym różni się to od przyjętej odpowiedzi? Czy tabela temp. Nie działałaby w przyjętej odpowiedzi?
John Saunders
1
Poprawny. Akceptowana odpowiedź nie działa w przypadku tabel tymczasowych, ponieważ „sys.columns” musi być określony jako „tempdb.sys.columns”, a nazwa tabeli musi być poprzedzona „tempdb ..”.
crokusek
10
select distinct object_name(sc.id)
from syscolumns sc,sysobjects so  
where sc.name like '%col_name%' and so.type='U'
Niszad
źródło
8

Odpowiedź pszenicy jest dobra, ale zakłada, że ​​nie masz identycznych par nazwa tabeli / nazwa kolumny w żadnym schemacie lub bazie danych. Aby zapewnić bezpieczeństwo w tym stanie, użyj tego ...

select *
from Information_Schema.Columns
where Table_Catalog = 'DatabaseName'
  and Table_Schema = 'SchemaName'
  and Table_Name = 'TableName'
  and Column_Name = 'ColumnName'
Daniel Barbalace
źródło
8

Istnieje kilka sposobów sprawdzenia istnienia kolumny. Zdecydowanie polecam używać, INFORMATION_SCHEMA.COLUMNSponieważ jest on tworzony w celu komunikowania się z użytkownikiem. Rozważ następujące tabele:

 sys.objects
 sys.columns

a nawet niektóre inne metody dostępu dostępne do sprawdzenia system catalog.

Nie musisz też używać SELECT *, po prostu przetestujNULL value

IF EXISTS(
           SELECT NULL 
           FROM INFORMATION_SCHEMA.COLUMNS
           WHERE
             TABLE_NAME = 'myTableName'
             AND COLUMN_NAME = 'myColumnName'
         ) 
Ali Elmi
źródło
1
Bez względu na to, nawet jeśli SELECT *z EXISTS, bo gdy jest używany istnieje tak naprawdę nie wybrać wszystkie wiersze i wszystkie kolumny wewnętrznie po prostu sprawdza istnienie oraz faktycznie sprawdza wszystkich wierszy i kolumn
Pawan Nogariya
7

Jednym z najprostszych i zrozumiałych rozwiązań jest:

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
źródło
7

Oto prosty skrypt, którego używam do zarządzania dodawaniem kolumn w bazie danych:

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

W tym przykładzie wykonania, Namejest to ColumnName, aby być dodawane Object_IdjestTableName

UJS
źródło
4

Poniższe zapytanie może służyć do sprawdzenia, czy przeszukiwana kolumna istnieje w tabeli, czy nie. Możemy podjąć decyzję na podstawie wyszukiwanego wyniku, jak pokazano poniżej.

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
źródło
3

Kolejna odmiana ...

SELECT 
  Count(*) AS existFlag 
FROM 
  sys.columns 
WHERE 
  [name] = N 'ColumnName' 
  AND [object_id] = OBJECT_ID(N 'TableName')
Manuel Alves
źródło
1

table -> table script as -> new windows - masz skrypt projektowy. sprawdź i znajdź nazwę kolumny w nowych oknach

arnav
źródło
1

Wykonaj poniższe zapytanie, aby sprawdzić, czy kolumna istnieje w podanej tabeli:

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 Kryszna
źródło
1

Kolejnym wkładem jest następujący przykład, który dodaje kolumnę, jeśli nie istnieje.

    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

Mam nadzieję, że to pomoże. Simone

Simone Spagna
źródło
0
IF EXISTS(SELECT 1 FROM sys.columns 
      WHERE Name = N'columnName'
      AND Object_ID = Object_ID(N'schemaName.tableName'))

Powinno to być dość prostym sposobem i bezpośrednim rozwiązaniem tego problemu. Użyłem tego wiele razy w podobnych scenariuszach. Działa jak urok, bez wątpienia.

Ilangeeran
źródło
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
źródło
0

Zrób coś, jeśli kolumna nie istnieje:

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

Zrób coś, jeśli kolumna istnieje:

BEGIN
    IF (COL_LENGTH('[dbo].[Table]', 'Column ') IS NOT NULL)
    BEGIN
        //Do something
    END
END;
Jagjit Singh
źródło