Answers:
2017年1月更新-SQL Server 2016 + / Azure SQL数据库
SQL Server 2016和当前版本的Azure SQL数据库现在对函数,过程,表,数据库等具有以下语法(DROP IF EXISTS
):
DROP FUNCTION IF EXISTS dbo.fn_myfunc;
SQL Server 2016 Service Pack 1为模块(功能,过程,触发器,视图)添加了更好的功能,这意味着不会丢失权限或依赖项(CREATE OR ALTER
):
CREATE OR ALTER FUNCTION dbo.fn_myfunc ...
这两种语法增强功能都可以简化用于源代码控制,部署等的脚本。
但是,如果您正在使用...
旧版本
从Management Studio编写脚本时,您需要执行SQL Server的操作:
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继续执行,因此,无论该删除是否起作用,仍将(重新)创建该函数。)
请注意,如果删除该函数并重新创建它,则将失去权限,并可能还会丢失依赖项信息。
该错误是不言自明的。有几种修复方法。
使用GO
伪关键字和DROP
/ CREATE
将脚本在Management Studio中分成不同的批次。(请注意,关键字本身可以在Management Studio选项中进行更改,但这实际上是设置,因此建议您不要使用它)。
运行脚本(或脚本的选定部分)时,Management Studio会在GO
s 之间分隔脚本的每个块,然后将这些部分作为单独的批处理顺序发送到SQL Server。
使用动态SQL从另一个批次中发送单独的批次。
这是首选方法,因为这样您的脚本将不依赖于外部功能来正确执行。例如,如果您的应用程序具有数据库更新程序,则通常来说它将加载脚本文件,然后在目标服务器上执行它。您将必须像Management Studio一样添加逻辑来分隔批处理(注意:充满危险),或者编写脚本以使整个脚本可以作为一个批处理成功执行。
如另一个答案中所述,您可以CREATE
使用此方法(或DROP
/的其他组合CREATE
)进行测试/ 。我更喜欢做的是创建一个存根对象(如果该对象不存在),然后用于ALTER <object>
实际创建或更改。这种方法不会删除诸如权限或扩展属性之类的依赖关系,也不需要复制/粘贴容易出错的逻辑以在单个语句中执行CREATE
/ ALTER
。
这是我用于创建或更改标量函数的模板。我将其保留为读者练习,以使其适应其他类型的对象(存储的proc,触发器等)。
IF NOT EXISTS(SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[<schema>].[<function name>]') AND type IN ('FN', 'FS'))
EXEC sp_executesql N'CREATE FUNCTION [<schema name>].[<function name>] (@a int) RETURNS int AS BEGIN /* Stub */ RETURN @a END'
EXEC sp_executesql N'
ALTER FUNCTION [<schema name>].[<function name>]
/* ... */
'
GO
实际上添加一个脚本可确保脚本会中断,因为该脚本将IF
无处可去。
DROP
/ CREATE
场景-已编辑。谢谢。