我怀疑你会为你的问题找到一个最佳答案,因为可以有很多方法来实现你的目标,但我可以分享我们的过程以及我在过去 10 年中所做的事情所获得的一些见解描述。也许他们会帮助您确定适合您的解决方案。
首先,更新客户端数据库是一个难题。自从您安装了您的软件后,您永远不会真正知道他们可以对数据库做什么。我让客户将他们自己的表、视图甚至索引添加到我们的系统表中,因为他们认为系统需要它们。在升级目标数据库时,所有这些都会让人头疼,因为您不一定知道一开始的数据库状态。
其次,我喜欢你最初认为升级数据库的安装程序将是要走的路。然后我开始更多地考虑这个问题,在我们的案例中,至少 DBA 通常不是升级前端软件的人。我们还从许多客户那里听说,在服务器上安装任何东西对他们来说都是不可能的,所以回到第一条。
最后,我们选择构建自己的可执行文件,其中包含升级脚本以及 DBA \ 最终用户连接到服务器 \ 数据库并运行升级过程的能力。
(在我们的例子中,我们使用了许多包含我们专有商业智能的加密存储过程,这就是为什么我们不只是将脚本提供给客户。)
如果您还没有这样做,请将您的数据库纳入源代码控制!Visual Studio 和 Red-Gate 各自提供产品来促进这一点。我都用过,没有特别的偏好,但我会说使用你和你的团队感到舒服的东西。
当我们发布更新时,我们执行从源代码控制中的最新版本数据库到早期版本数据库的差异。我们寻找任何新对象和任何更改的对象 - 我们很少删除对象,但这可能也是您需要的。
一旦我们知道数据库中发生了什么变化,我们就会非常有条不紊地通过更改列表创建幂等脚本来执行必要的更改。这是一个非常繁琐的过程,但有助于确保客户获得轻松的升级体验。本质上,我们对这个过程所做的是防御性编程——而不是假设数据库中存在表、视图、存储过程、函数等,我们首先检查以确保该项目存在。如果是这样,我们也许可以完全跳过该 DDL 语句。在其他情况下,我们可能希望删除对象并重新创建它。
需要明确的是,我们从不删除表,但我们经常会删除其他对象并重新创建它们以确保对象是最新的。
脚本以正确的顺序打包到我们的可执行文件(我们内部构建的解决方案)中(例如,如果您要添加一个表和一个引用该表的视图,则需要在视图之前创建该表)。
顺便说一句,Red-Gate 提供了一个现在为您执行此操作的工具,尽管我还没有在生产中亲自使用它。
一旦我们对更新已正确打包感到高兴,我们就会尝试破解它!我们在我们支持的所有 SQL Server 版本(例如 2000、2005、2008、2012)上针对我们数据库的各种版本进行测试——真正的旧版本、我们以一种或另一种方式修改过的数据库。如果我们发现一种情况不起作用,我们会修复我们的脚本,直到它发生。
我还应该提到,我们的数据库模式有一个日志表,我们的更新模块写入该日志表,以便记录执行更新的时间、执行者以及哪些对象是该更新的一部分。这有时有助于排除故障。
虽然我们的实用程序不会在执行脚本之前备份要升级的数据库,但我们可以,而且我建议您将其视为过程的一部分。(我们的文档强调了这一点的重要性,并且我们多年来与之合作的大多数 DBA 也自然而然地这样做了,因此我们认为没有必要将其写入实用程序中)。
数据库更新实用程序与我们的软件更新打包在一起,并作为整个产品的另一个组件分发,并且可以由在我们客户端站点的数据库中拥有适当凭据和权限的任何用户执行。
虽然多年来这个过程对我们来说效果很好,但随着新工具在市场上的引入以及我们遇到客户遇到的错误,我们会继续对其进行改进。开发一个有效的过程可能需要一段时间,所以尽量不要在任何给定时间咀嚼太多。对我们来说,将数据库纳入源代码控制是最大的关键。一旦我们这样做了,事情就开始逐渐到位。