Aktualizacja stycznia 2017 r. - SQL Server 2016+ / Azure SQL Database
SQL Server 2016 i bieżąca wersja bazy danych SQL Azure ma teraz następującą składnię dla funkcji, procedur, tabel, baz danych itp. ( DROP IF EXISTS
):
DROP FUNCTION IF EXISTS dbo.fn_myfunc;
Dodatek Service Pack 1 dla programu SQL Server 2016 dodaje jeszcze lepszą funkcjonalność modułów (funkcje, procedury, wyzwalacze, widoki), co oznacza brak utraty uprawnień lub zależności ( CREATE OR ALTER
):
CREATE OR ALTER FUNCTION dbo.fn_myfunc ...
Oba te ulepszenia składni mogą prowadzić do znacznie prostszych skryptów używanych do kontroli źródła, wdrażania itp.
Ale jeśli używasz ...
starsza wersja
Musisz zrobić to, co robi SQL Server, kiedy piszesz to z Management Studio:
IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE type = 'FN' AND name = 'fn_myfunc')
BEGIN
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'CREATE FUNCTION ...';
EXEC sp_executesql @sql;
END
Lub możesz powiedzieć:
BEGIN TRY
DROP FUNCTION dbo.fn_myfunc;
END TRY
BEGIN CATCH
PRINT 'Function did not exist.';
END CATCH
GO
CREATE FUNCTION...
Lub możesz po prostu powiedzieć:
DROP FUNCTION dbo.fn_myfunc;
GO
CREATE FUNCTION...
(Tutaj pojawi się komunikat o błędzie, jeśli funkcja jeszcze nie istnieje, ale skrypt będzie kontynuował od następnego GO, więc niezależnie od tego, czy upuszczenie działało, czy nie, funkcja będzie nadal (ponownie) tworzona).
Pamiętaj, że jeśli upuścisz tę funkcję i utworzysz ją ponownie, utracisz również uprawnienia i potencjalnie informacje o zależnościach.
Błąd jest dość oczywisty. Istnieje kilka sposobów, aby to naprawić.
Rozdziel skrypt na różne partie w Management Studio za pomocą
GO
pseudo-słowa kluczowego iDROP
/CREATE
obiektu. (Pamiętaj, że samo słowo kluczowe można zmienić w opcjach Management Studio, ale jest to ustawienie de facto, więc sugeruję pozostawienie go w spokoju).Po uruchomieniu skryptu (lub wybranej części skryptu) Management Studio oddziela każdą część skryptu między
GO
s i kolejno wysyła części do SQL Server jako osobne partie.Użyj dynamicznego SQL, aby wysłać osobną partię z innej partii.
Jest to preferowana metoda, ponieważ wtedy twój skrypt nie zależy od zewnętrznej funkcjonalności, aby poprawnie się uruchomić. Na przykład, jeśli aplikacja ma program do aktualizacji bazy danych, ogólnie mówiąc, załaduje plik skryptu, a następnie uruchomi go na serwerze docelowym. Albo będziesz musiał dodać logikę, aby oddzielić partie, jak robi to Management Studio (uwaga: pełna niebezpieczeństw), lub napisać skrypt w taki sposób, aby cały skrypt mógł zostać pomyślnie wykonany jako pojedyncza partia.
Jak wspomniano w innej odpowiedzi, możesz wykonać test /
CREATE
przy użyciu tej metody (lub innej kombinacjiDROP
/CREATE
itp.). Wolę utworzyć obiekt pośredniczący, jeśli obiekt nie istnieje, a następnie użyćALTER <object>
go do utworzenia lub zmiany. To podejście nie usuwa zależności, takich jak uprawnienia lub właściwości rozszerzone, i nie jest konieczne kopiowanie / wklejanie podatnej na błędy logiki, aby wykonaćCREATE
/ALTER
w pojedynczej instrukcji.Oto szablon, którego używam do tworzenia lub zmiany funkcji skalarnej. Zostawię to jako ćwiczenie dla czytelnika, aby dostosować to do innych typów obiektów (przechowywane procy, wyzwalacze itp.).
źródło
GO
rzeczywiście gwarantuje, że skrypt się zepsuje, ponieważIF
nie doprowadzi do nikąd.DROP
/CREATE
scenariuszu. Dzięki.Możesz sprawdzić, czy obiekt istnieje,
database
i utworzyć, jeśli nie:źródło