如果存储过程尚不存在,则创建它,但不要更改也不要删除现有的存储过程

Posted

技术标签:

【中文标题】如果存储过程尚不存在,则创建它,但不要更改也不要删除现有的存储过程【英文标题】:Creating a stored procedure if it does not already exist, but do not alter and do not drop the existing one 【发布时间】:2020-05-26 12:48:20 【问题描述】:

我找到了一些示例,其中删除或更改了存储过程以防万一。

但是如何编写一个严格执行以下操作的 T-SQL 批处理脚本:

检查存储过程是否存在: 如果它存在,则脚本什么都不做 - 我不想放弃并重写或更改现有程序,因为它可能有其他人所做的更改。此外,脚本不应因错误而中止,因为它可能是较大批量更改的一部分。 如果它不存在,则只能使用我的代码创建一个新过程

?

【问题讨论】:

得到错误是否足够好?因为如果您运行 create procedure 语句并且该过程已经存在,那么 SQL Server 将引发错误“数据库中已经存在一个名为“您的过程名称”的对象。”... 你提出了一个很好的观点@ZoharPeled。 它需要是原子的吗?如果是这样,并且如果只有您的代码将在此 SP 的沙箱中播放,您可能需要使用 application lock 来保护操作免受多次调用。 它可能有其他人所做的更改您需要一个源代码控制系统,这样更改/版本就不会丢失。以及不允许对代码进行随机、未记录、未审查和未测试的更改的变更管理流程。 @SMor 你是对的。不幸的是,有时生活很粗糙,一个数据库可能由两个不同的团队维护,他们互相抛出随机的 SQL 脚本。 【参考方案1】:

创建存储过程时,它可以是批处理中的唯一语句。这意味着像下面这样的事情会失败:

IF NOT EXISTS(SELECT 1 FROM sys.schemas s JOIN sys.procedures p ON s.schema_id = p.schema_id WHERE s.[name] = N'dbo' AND p.[name] = N'YourProcedure') BEGIN

    CREATE PROC dbo.YourProcedure @TableName sysname AS
    BEGIN

        SELECT *
        FROM sys.tables t
        WHERE t.name = @TableName;

    END;
END;

因此,如果要先检查过程是否存在,如果不存在则创建它,则必须使用“动态”SQL(它并不是真正的动态,因为其中没有任何动态):

IF NOT EXISTS(SELECT 1 FROM sys.schemas s JOIN sys.procedures p ON s.schema_id = p.schema_id WHERE s.[name] = N'dbo' AND p.[name] = N'YourProcedure') BEGIN

    EXEC sys.sp_executesql N'CREATE PROC dbo.YourProcedure @TableName sysname AS
BEGIN

    SELECT *
    FROM sys.tables t
    WHERE t.name = @TableName;

END;';
END;

这意味着在将存储过程的定义中的任何单引号粘贴到动态语句中时,您需要对其进行转义。

【讨论】:

谢谢,所以我想我将不得不采用这个丑陋的字符串化解决方案。微软有时会做出奇怪的决定。

以上是关于如果存储过程尚不存在,则创建它,但不要更改也不要删除现有的存储过程的主要内容,如果未能解决你的问题,请参考以下文章

jQuery搜索文本页面并更改它,但如果它已经存在则不要

spark:模式更改——如果存在,则转换和过滤列上的数据框;如果没有就不要

如果不存在则插入数据的过程pl sql

Swift 2.1 Core Data - 保存具有一对多关系的数据,但如果已经存在则不要添加异构数据

如果文件存在,如何锁定文件,不要创建它?

不要在突变处理程序之外改变 vuex 存储状态