Обновление от января 2017 г. - SQL Server 2016+ / База данных SQL Azure
SQL Server 2016 и текущая версия базы данных SQL Azure теперь имеют следующий синтаксис для функций, процедур, таблиц, баз данных и т. Д. ( DROP IF EXISTS
):
DROP FUNCTION IF EXISTS dbo.fn_myfunc;
А SQL Server 2016 с пакетом обновления 1 (SP1) добавляет еще улучшенную функциональность для модулей (функций, процедур, триггеров, представлений), что означает отсутствие потери разрешений или зависимостей ( CREATE OR ALTER
):
CREATE OR ALTER FUNCTION dbo.fn_myfunc ...
Оба эти улучшения синтаксиса могут привести к гораздо более простым сценариям, используемым для управления исходным кодом, развертываниям и т. Д.
Но если вы используете ...
Старые версии
Вам нужно сделать то, что делает SQL Server, когда вы пишете сценарий из 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
Или вы можете сказать:
BEGIN TRY
DROP FUNCTION dbo.fn_myfunc;
END TRY
BEGIN CATCH
PRINT 'Function did not exist.';
END CATCH
GO
CREATE FUNCTION...
Или вы можете просто сказать:
DROP FUNCTION dbo.fn_myfunc;
GO
CREATE FUNCTION...
(Здесь вы получите сообщение об ошибке, если функция еще не существует, но сценарий будет продолжен со следующего GO, так что независимо от того, сработало удаление или нет, функция все равно будет (повторно) создана.)
Обратите внимание, что если вы удалите функцию и создадите ее заново, вы потеряете права доступа и, возможно, информацию о зависимостях.
Ошибка довольно очевидна. Есть несколько способов исправить это.
Разделяйте сценарий на разные пакеты в Management Studio, используя
GO
псевдоключевое слово иDROP
/CREATE
object. (Обратите внимание, что само ключевое слово можно изменить в параметрах Management Studio, но это де-факто параметр, поэтому я предлагаю оставить его в покое).Когда вы запускаете сценарий (или выбранную часть сценария), Management Studio разделяет каждый фрагмент сценария между
GO
s и последовательно отправляет части в SQL Server в виде отдельных пакетов.Используйте динамический SQL для отправки отдельного пакета из другого пакета.
Это предпочтительный метод, потому что тогда ваш скрипт не зависит от внешней функциональности для правильного выполнения. Например, если ваше приложение имеет программу обновления базы данных, то, вообще говоря, оно загрузит файл сценария и затем выполнит его на целевом сервере. Либо вам придется добавить логику для разделения пакетов, как это делает Management Studio (примечание: чревато опасностью), либо написать сценарий таким образом, чтобы весь сценарий мог быть успешно выполнен в виде одного пакета.
Как уже упоминалось в другом ответе, вы можете выполнить тест /
CREATE
с помощью этого метода (или какой-либо другой комбинацииDROP
/CREATE
и т. Д.). Что я предпочитаю делать, так это создавать объект-заглушку, если объект не существует, а затем использовать егоALTER <object>
для создания или изменения. Этот подход не удаляет зависимости, такие как разрешения или расширенные свойства, и нет необходимости копировать / вставлять подверженную ошибкам логику, чтобы выполнитьCREATE
/ALTER
в одном выражении.Вот шаблон, который я использую для создания или изменения скалярной функции. Я оставлю это в качестве упражнения для читателя, чтобы адаптировать его к другим типам объектов (хранимые процессы, триггеры и т. Д.).
источник
GO
фактически гарантирует, что скрипт сломается, так какIF
он ни к чему не приведет.DROP
/CREATE
сценарий - отредактировано. Благодарю.У вас есть возможность проверить, существует ли объект в
database
и создать, если нет:источник