Dodaj kolumnę do tabeli, jeśli jeszcze nie istnieje


188

Chcę napisać zapytanie do MS SQL Server, które dodaje kolumnę do tabeli. Ale nie chcę wyświetlać żadnych błędów, gdy uruchamiam / wykonuję następujące zapytanie.

Używam tego rodzaju zapytań, aby dodać tabelę ...

IF EXISTS (
       SELECT *
       FROM   sys.objects
       WHERE  OBJECT_ID = OBJECT_ID(N'[dbo].[Person]')
              AND TYPE IN (N'U')
   )

Ale nie wiem, jak napisać to zapytanie dla kolumny.



Powinieneś użyć sys.tableszamiast „ogólnego” sys.objects- wtedy nie musisz jawnie określać typu (to oczywiste z sys.tablesjuż ....)
marc_s

COL_LENGTH Alternative działa tylko z SQL-Server 2008, ale działa.
Paul-Henri,

Odpowiedzi:


219

Możesz użyć podobnej konstrukcji, korzystając z sys.columnstabeli io sys.objects.

IF NOT EXISTS (
  SELECT * 
  FROM   sys.columns 
  WHERE  object_id = OBJECT_ID(N'[dbo].[Person]') 
         AND name = 'ColumnName'
)

42
Zauważ, że w tym przypadku chcesz użyć JEŻELI NIE ISTNIEJE w swoim kodzie.
Nat

2
Aby zoptymalizować zapytanie, możesz użyć pierwszej 1 z instrukcją select
Banketeshvar Narayan

11
@BanketeshvarNarayan to jest nieprawidłowe. Plany wykonania dla podzapytań w EXISTSklauzuli są identyczne. Rzeczy takie jak SELECT 1lub SELECT TOP 1są niepotrzebne. Sama EXISTSklauzula mówi optymalizatorowi zapytań, aby wykonywał tylko minimalne odczyty niezbędne do oceny EXISTS... przynajmniej w SQL Server. Inne silniki DB mogą mieć mniej lub bardziej wydajny optymalizator zapytań.
Kenneth Cochran

9
@BanketeshvarNarayan Jeśli optymalizujesz swoje ADD Columnzapytania ... musisz je uruchamiać zbyt często!
Fenton

1
@ user391339 - Wysłałem konstrukcję podobną do opublikowanej przez OP, ale tak, jeśli chcesz podjąć działanie, jeśli kolumna nie istnieje, instrukcja będzie JEŚLI NIE ISTNIEJE. Naprawdę nie czuję potrzeby edytowania odpowiedzi na to pytanie, ale nie waham się edytować samodzielnie, jeśli uważasz, że to poprawa.
Lieven Keersmaekers

91
IF COL_LENGTH('table_name', 'column_name') IS NULL
BEGIN
    ALTER TABLE table_name
    ADD [column_name] INT
END

1
Próbowałem to zrobić, ale zwraca błąd informujący, że funkcja COL_LENGTH nie istnieje.
ThEpRoGrAmMiNgNoOb

3
Wymaga SQL Server 2008+
Robert Brown

6
Mały dodatek - nie należy używać nawiasów kwadratowych w nazwie kolumny, ponieważ COL_LENGTH('table_name', '[column_name]')zawsze zwraca wartość null w SQL Server 2016 ( COL_LENGTH('[table_name]', 'column_name') works as expected).
stop-cran

33

Kolejna alternatywa. Wolę takie podejście, ponieważ jest mniej pisania, ale obydwoje osiągają to samo.

IF COLUMNPROPERTY(OBJECT_ID('dbo.Person'), 'ColumnName', 'ColumnId') IS NULL
BEGIN
    ALTER TABLE Person 
    ADD ColumnName VARCHAR(MAX) NOT NULL
END

Zauważyłem również, że twój szuka tam, gdzie istnieje stół, to oczywiście tylko to

 if COLUMNPROPERTY( OBJECT_ID('dbo.Person'),'ColumnName','ColumnId') is not null

2
Lubię to. Myślę, że najlepszą częścią publikowania tutaj jest znalezienie takich klejnotów.
JStead

2
Co to jest „ColumnId”?
Marius Stănescu,

„ColumnId” to nazwa właściwości kolumny, względem której sprawdzasz. Prawdopodobnie mogłeś użyć dowolnej nazwy właściwości istniejącej w kolumnie, takiej jak nazwa itp.
Jacques Bosch

5

Oto kolejna odmiana, która zadziałała dla mnie.

IF NOT EXISTS (SELECT 1
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE upper(TABLE_NAME) = 'TABLENAME'
        AND upper(COLUMN_NAME) = 'COLUMNNAME')
BEGIN
    ALTER TABLE [dbo].[Person] ADD Column
END
GO

EDYCJA: Pamiętaj, że INFORMATION_SCHEMAwidoki nie zawsze mogą być aktualizowane, SYS.COLUMNSzamiast tego użyj :

IF NOT EXISTS (SELECT 1 FROM SYS.COLUMNS....



0

Sprawdzając kolumnę w innej bazie danych, możesz po prostu dołączyć nazwę bazy danych:

IF NOT EXISTS (
  SELECT * 
  FROM   DatabaseName.sys.columns 
  WHERE  object_id = OBJECT_ID(N'[DatabaseName].[dbo].[TableName]') 
         AND name = 'ColumnName'
)

-1
IF NOT EXISTS (SELECT 1  FROM SYS.COLUMNS WHERE  
OBJECT_ID = OBJECT_ID(N'[dbo].[Person]') AND name = 'DateOfBirth')
BEGIN
ALTER TABLE [dbo].[Person] ADD DateOfBirth DATETIME
END
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.