【问题标题】:How should I rename many Stored Procedures without breaking stuff?我应该如何在不破坏内容的情况下重命名许多存储过程?
【发布时间】:2011-03-19 12:58:27
【问题描述】:

多年来,我的数据库有几个连续的维护者,任何可能曾经存在的命名准则都被忽略了。

我想将存储过程重命名为一致的格式。显然我可以在 SQL Server Management Studio 中重命名它们,但这不会更新在后面的网站代码 (C#/ASP.NET) 中进行的调用。

我能做些什么来确保所有调用都更新为新名称,而不是在代码中搜索每个旧过程名称? Visual Studio 是否有能力重构此类存储过程名称?

注意,我不认为我的问题与 this question 重复,因为后者只是关于在数据库中重命名。

【问题讨论】:

  • 我想不出别的了。您可以重新生成一些层,但最终您将不得不编辑代码。
  • 这是一个令人钦佩的想法,但实际上您不应该尝试这样做。当您必须对程序进行更改时,您可以重命名它,但突然这样做只是在寻找麻烦。他们说,“如果它没有坏,就不要修理它。”
  • @Fosco 嗯,有趣的一点。然而,虽然它在功能上没有被破坏,但它在设计上被破坏了,这使得查找存储过程变得困难。为了安全起见,我正在删除现有的纯文本 SQL 调用,并用参数化的存储过程替换它们。有时可能已经使用了一个。

标签: sql-server visual-studio stored-procedures renaming


【解决方案1】:

这是假设您使用 SQL Server 2005 或更高版本。我之前使用的一个选项是重命名旧数据库对象并使用旧名称创建 SQL Server 同义词。这将允许您将对象更新为您选择的任何约定,并在您使用它们时替换代码、SSIS 包等中的引用。然后,您可以集中精力逐步更新代码中的引用,而不是您选择的维护版本(而不是一次全部破坏)。当您觉得您已找到所有参考资料时,您可以在代码进入 QA 时删除同义词。

【讨论】:

    【解决方案2】:

    我完全赞成重构任何类型的代码。

    您真正需要的是一种缓慢且渐进地重命名存储过程的方法。
    我当然不会进行全局查找和替换。

    相反,当您确定小块功能并了解 proc 之间的关系时,您可以重新考虑小块。

    但是,此过程的基础是对数据库的源代码控制。
    如果您没有像管理普通代码一样管理对数据库的更改,那么您将遇到严重的麻烦。

    看看 DBSourceTools。 http://dbsourcetools.codeplex.com
    它专门设计用于帮助开发人员将他们的数据库置于源代码控制之下。

    在重构之前,您需要一种可重复的方法将数据库恢复到特定状态。
    然后以受控方式重新应用重构后的更改。

    一旦你接受了这种心态,这个庞大且容易出错的任务就会变得简单。

    【讨论】:

      【解决方案3】:
      1. 我将使用以下内容获取对过程的引用列表,因为 SSMS 依赖项不会获取动态 SQL 引用或数据库外部的引用。

        SELECT OBJECT_NAME(m.object_id), m.*
          FROM SYS.SQL_MODULES m
         WHERE m.definition LIKE N'%my_sproc_name%'
        
        • SQL 需要在每个可能存在引用的数据库中运行。
        • syscmets 和 INFORMATION_SCHEMA.routines 具有 nvarchar(4000) 列。因此,如果在位置 3998 处使用了“mySprocName”,则不会找到它。 syscmets 确实有多行,但 ROUTINES 会截断。 Should you disagree, take it up with gbn
      2. 基于该依赖关系列表,我将创建新的存储过程以启动基础存储过程 - 那些具有最少依赖关系的存储过程。但我会mind not to create stored procedures, prefixing the name with "sp_"
      3. 验证基础程序与现有程序的工作方式相同
      4. 移动到下一级存储过程 - 根据需要重复步骤 1-3,直到处理完最高级别的过程。
      5. 测试应用程序使用到新过程的切换 - 不要等到所有过程都更新后才能测试与应用程序代码的交互。不需要对每个存储过程都执行此操作,但等待批量执行此操作也不是一个好方法。

      并行开发也有风险:

      • 对现有代码的任何更改也需要应用于新代码。如果可能,请在开发被冻结的领域工作,或者利用错误修复作为迁移到新代码的机会,而不是在两个地方应用补丁(同时还可以最大限度地减少过渡的停机时间)。

      【讨论】:

        【解决方案4】:

        您至少需要在两个方面处理这个问题,即应用程序和数据库。可能还有其他区域,您必须小心不要忽视它们。

        应用程序

        未来项目的良好实践

        它有助于抽象出你的存储过程。在我们的应用程序中,我们将所有存储过程封装在一个巨大的类中,我可以这样调用:

        Dim SomeData as DataTable = Sprocs.sproc_GetSomeData(5)
        

        这样,代码端就很好了,并且被封装了。我可以进入 Sprocs.sproc_GetSomeData 并在一个地方调整 sproc 名称,当然我可以右键单击该方法并进行符号重命名以修复解决方案范围内的方法调用。

        没有抽象

        如果没有这种抽象,您只需对 sproc 名称执行 Find In Files (Cntl+Shift+F),然后如果结果看起来正确,打开文件并查找/替换所有出现。

        Sql 服务器

        不要信任视图依赖项

        在 SQL 服务器端,理论上在 MSSMS 2008 中,您可以右键单击存储过程并选择查看依赖项。 应该向您显示数据库中使用 sproc 的所有位置的列表,但是我对此功能的信心非常低。在 SQL 2008 中可能会更好,但在以前的版本中肯定有问题。

        View Dependencies 伤害了我,这需要时间来治愈。 :)

        包起来!

        你最终不得不保留旧的 sproc 一段时间。这就是为什么重命名 sprocs 是一个这样的项目的主要原因 - 最终可能需要一个月才能完成。

        首先用一些简单的 TSQL 替换它的内容,该 TSQL 使用相同的参数调用新的 sproc,并编写一些日志记录,以便一段时间后,您可以判断旧的 sproc 是否实际上未使用。

        最后,当您确定旧的存储过程未被使用时,将其删除。

        其他地区?

        可能还有很多其他领域。报告服务浮现在脑海中。 SSIS 包。使用保留旧存储区并重新路由到新存储区的技术(如上所述)将帮助您了解是否错过了任何内容,但它不会告诉您错过了什么。这会导致很多痛苦!

        祝你好运!

        【讨论】:

        • 嗯,包装存储过程是一个有趣的做法。
        【解决方案5】:

        我会更关心忽略过程的名称并用 Enterprise Library Data Access Block 5 替换您的旧 DAL

        Database Accessors in Enterprise Library 5 DAAB - Database.ExecuteSprocAccessor

        有类似的代码

         public Contact FetchById(int id)
         {
          return _database.ExecuteSprocAccessor<Contact>
           ("FetchContactById", id).SingleOrDefault();
         }
        

        与具有一致名称的存储过程相比,其价值至少高出 10 亿倍,尤其是在当前代码绕过 DataTables 或 DataSets ::shudders::

        【讨论】:

          【解决方案6】:

          使用FileSeek 之类的实用程序来搜索项目文件夹中每个文件中的内容。不要相信 Windows 搜索 - 它速度慢且对用户不友好。

          因此,如果您有一个名为 OldSprocOne 的存储过程并希望将其重命名为 SP_NewONe,请搜索所有出现的 OldSprocOne,然后搜索所有出现OldSprocOne 以查看该名称是否尚未在其他地方使用并且不会引起问题。然后重命名代码中的每一个匹配项。

          这对于大型系统来说可能非常耗时且重复。

          【讨论】:

            【解决方案7】:

            恐怕在您的源代码和其他数据库对象中搜索会有点乏味。

            不要忘记 SSIS 包、SQL 代理作业、Reporting Services rdl 以及您的主要应用程序代码。

            如果您有一个支持使用正则表达式搜索文件的工具(我过去曾为此使用过 RegexBuddy )

            如果您只想说明您可能错过了一个奇怪的可能性,您可以将所有以前的存储过程留在一个月,然后让它们记录a custom SQL trace eventAPP_NAME(), SUSER_NAME() 以及您认为有用的任何其他信息让它调用重命名的版本。然后设置跟踪监视此事件。

            【讨论】:

              【解决方案8】:

              您可以将 SPROC 的“胆量”移动到符合新命名约定的新 SPROC,然后将原始 sproc 保留为委托给新 SPROC 的外壳/包装器。 您还可以添加一个“审计”表来跟踪调用旧包装器 SPROC 的时间 - 这样您将知道旧 SPROC 没有依赖关系,并且可以安全地删除旧 SPROC(另外,请确保它是'不仅仅是使用数据库的'你的应用' - 例如跨数据库连接或其他应用)

              这会带来很小的性能损失,并且不会真正为您带来太多好处(除了能够更轻松地“找到”您的新 SPROC)

              【讨论】:

                【解决方案9】:

                我这样做了,我在源代码中严重依赖全局搜索来查找存储过程名称和 SQL 挖掘器来查找调用 sql 过程的 sql 过程。

                http://www.sqldigger.com/

                SQL Server(自 SQL 2000 起)对其自身的依赖关系了解甚少,因此只能搜索脚本文本以查找依赖关系,这可能是其他存储的过程或动态 sql 的子字符串。

                【讨论】:

                  【解决方案10】:

                  至于更改您的应用程序,我将所有存储的过程作为设置在 web.config 文件中,因此所有名称都在一个位置,并且可以随时更改以匹配对数据库的更改。

                  当应用程序需要调用存储过程时,名称由 web.config 确定。

                  这使得管理应用程序可能对数据库服务层进行的所有潜在调用变得更加容易。

                  【讨论】:

                    【解决方案11】:

                    您可以分阶段进行更改:

                    1. 将存储过程复制到新名称下的新存储过程。
                    2. 更改旧存储过程以调用新存储过程。
                    3. 在您更改网站中的所有代码后,将日志记录添加到旧的存储过程中。
                    4. 一段时间后,当您没有看到对旧存储过程的任何调用并且您很高兴在网站中找到了所有调用时,您可以删除旧存储过程和日志记录。

                    【讨论】:

                    • 我还应该说的一件事:首先备份您的存储过程!以防万一您需要让它们恢复原状!
                    • 防御性数据库开发的好例子!
                    【解决方案12】:

                    如果您使用到 DB、存储过程等的连接,您应该创建一个服务类来委派这些方法。

                    这样,当您的数据库、SP 等发生变化时,您只需更新您的服务类,并且所有内容都受到保护,不会被破坏。

                    有一些用于 VS 的工具可以管理更改名称,例如 refactor 和 resharper

                    【讨论】:

                      【解决方案13】:

                      没有测试应用程序中的每条路径以确保对数据库和相关存储过程的任何调用都已更新...不。

                      使用全局搜索和替换(但检查每个建议的替换)来尽量避免遗漏任何实例。如果您的应用程序结构良好,那么每个存储过程实际上应该只有 1 个位置被调用。

                      【讨论】:

                        猜你喜欢
                        • 2015-05-02
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-01-29
                        • 1970-01-01
                        • 2010-11-04
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多