Dodawanie kolumny w SQL Server tylko wtedy, gdy nie istnieje
Wyobraźmy sobie następującą sytuację: musimy zmodyfikować strukturę tabeli w SQL Server, a dokładniej - dodać do niej kolumnę. Przygotowujemy sobie prosty skrypt, który nam takie zadanie wykona:
Proste i przejrzyste, więc nie wymaga komentarza.
Kolejną sytuacją do wyobrażenia sobie będzie kilku klientów, z których każdy ma różną wersję bazy. Co jest w naszym przypadku istotne - niektórzy klienci mają już częściowo zaktualizowaną bazę i mają kolumnę MyColumn w tabeli MyTable, natomiast inni klienci takiej kolumny nie mają. Co wtedy zrobić? Prosty skrypt nie wystarczy. Gdy klient danej kolumny nie ma, skrypt zadziała właściwie. Gdy ma, skrypt zakończy się błędem i wielce prawdopodobne jest, że przerwie jednocześnie całą procedurę aktualizacji. Co wtedy zrobić? Jedno z rozwiązań pokazane jest poniżej:
WHERE TABLE_SCHEMA='dbo' AND TABLE_NAME = 'MyTable' AND COLUMN_NAME = 'MyColumn')
BEGIN
ALTER TABLE dbo.RollupTable ADD Aaa int
END
Można to wszystko jeszcze bardziej udoskonalić i napisać sobie procedurę składowaną. Istnieje wiele możliwości napisania takiego skryptu. Najczęściej wykorzystywaną przeze mnie wersją jest ta zaprezentowana poniżej:
@table nvarchar(128),
@column nvarchar(128)
AS
DECLARE @iDot int
SELECT @iDot=CHARINDEX('.', @table)
DECLARE @sch nvarchar(64) = SUBSTRING(@table, 1, @iDot-1)
DECLARE @tab nvarchar(64) = SUBSTRING(@table, @iDot+1, 128)
DECLARE @iSeparator int
SELECT @iSeparator=CHARINDEX(' ', @column)
DECLARE @col nvarchar(64) = SUBSTRING(@column, 1, @iSeparator-1)
DECLARE @type nvarchar(64) = SUBSTRING(@column, @iSeparator+1, 128)
DECLARE @sql nvarchar(1024) =
'IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS '+
'WHERE TABLE_SCHEMA='''+@sch+''''+
' AND TABLE_NAME = '''+@tab+''''+
' AND COLUMN_NAME = '''+@col+''') '+
'BEGIN'+
' ALTER TABLE '+@sch+'.'+@tab+' ADD '+@col+' '+@type+' '+
'END'
EXEC sp_sqlexec @sql
Pierwszym parametrem jest nazwa tabeli wraz ze schematem ('dbo.MyTable'). Drugi parametr to nazwa kolumny oraz typ kolumny (MyColumn int). Jak można zauważyć, pola w pierwszym parametrze oddzielone są kropką (w stylu SQL Server), natomiast pola w drugim parametrze oddzielone są spacją (też na wzór instrukcji SQL MyColumn int). Można to rozdzielić na więcej parametrów, ale taka wersja wydała mi się najbardziej przyjazna i intuicyjna. Należy przy tym pamiętać, że procedura zakończy się błędem w przypadku nieprawidłowych argumentów. Jeżeli podamy nazwę tabeli bez przestrzeni (czyli MyTable zamiast dbo.Table) lub nazwa kolumny w drugim parametrze będzie zawierała spację ('[My Column] int') to nie oczekujmy właściwych rezultatów. Da się to obejść, ale czasami po prostu nie warto. Wystarczy mieć świadomość tych konsekwencji i w takich kontrowersyjnych przypadkach z tej procedury nie korzystać. Doświadczenie pokazuje, że taka wersja nadaje się do zdecydowanej większości zadań.
Wywołanie tej procedury jest bajecznie proste. Może to być na przykład taka instrukcja:
Kategoria:SQL Server
Brak komentarzy - bądź pierwszy