温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

SQL Compare怎样使用SQL比较命令行从源代码管理中进行自定义部署

发布时间:2021-11-10 09:51:10 来源:亿速云 阅读:130 作者:柒染 栏目:大数据

这期内容当中小编将会给大家带来有关SQL Compare怎样使用SQL比较命令行从源代码管理中进行自定义部署,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

SQL Compare是一款比较和同步SQL Server数据库结构的工具。现有超过150,000的数据库管理员、开发人员和测试人员在使用它。当测试本地数据库,暂存或激活远程服务器的数据库时,SQL Compare将分配数据库的过程自动化。

Giorgi Abashidze解释了他的团队如何使用带有SQL Compare命令行和一些SQL同义词的两阶段部署过程来自动为其每个客户进行自定义部署,而只需要在源代码管理中为每个版本维护一个分支。

在我以前的文章中,从使用SQL比较命令行的源代码控制到数据库,我解释了我的团队如何使用SQL比较命令行为我们的客户自动化数据库部署,而无需访问实际的暂存数据库或生产数据库,这是不可能的这是一个银行数据库。我展示了如何通过仅访问我们的开发数据库(包含在TFS源代码管理下),如何使用SQL Compare命令行来部署数据库元数据和所有客户通用的代码。

但是,除了此共享代码外,还必须为我们的每个客户提供每个软件版本的独特变体,以便向他们提供可满足其不同业务和合规性要求的自定义例程。我们每个客户都需要其中一些例程,当然,此专有功能应始终仅部署到该客户的生产数据库中:至关重要的是,任何客户都不能看到专门为另一位客户编写的逻辑。

我们如何实现这一目标?传统的观点似乎是,在每个发行版中,我们将数据库版本的每个特定于客户的变体视为一个单独的分支。但是,这可能会增加构建的复杂性。有了一些创造力,我们可以避免这种情况,而是为每个新版本创建一个分支,我们可以使用该分支来维护和部署我们每个客户的所有共享逻辑,以及专用于无限数量客户的逻辑。

在本文中,我将说明如何使用SQL Compare命令行,同义词和一些独创性来完成所有这些工作。

我们如何将客户特定的例程存储在单个数据库中

因此,为了更接近我们的开发数据库的构建方式,我们假设我们的Trunk结合了我们所有的逻辑。假设我们有三个客户Cust1,Cust2和Cust3。

我们还有一些代码,即SQL存储过程,称为SQL存储过程loan.calculate_effective_rate,该过程根据某种算法来计算在一段时间内对贷款支付的实际利率,称为“有效利率”。对于所有客户来说,这是相同的代码,但是有一天,客户Cust1要求我们更改其版本的算法,这意味着我们现在需要维护和部署“有效率”过程的两个不同版本。

首先,我们需要effective_rate按照Cust1的要求,为该过程实现替代算法(从这里开始,我将使用其名称的这种缩写形式)。我们只有一个开发数据库,称为Trunk,并且由于任何例程中每个例程的名称都必须唯一,这意味着我们必须有一种命名策略来区分这些变体。

我们这样做的方法是:

  1. 将effective_rate过程重命名为effective_rate_default,为我们的客户创建默认的计算实现。

  2. 创建一个名为的新过程effective_rate_cust1。就参数和参数类型而言,它应具有与旧签名相同的签名。这必须仅部署到Cust1组织。

这意味着所有客户的应用程序代码现在都必须调用该effective_rate_default过程,但必须调用的Cust1除外effective_rate_cust1。但是,我们不希望对任何客户的调用代码进行任何更改。毕竟,该程序的目的没有改变,但是我们现在有多个实施同一操作(计算贷款的有效利率)的方法。相反,我们使用同义词表示具有多个实现的任何动作。换句话说,调用者代码从不直接调用确切的实现,而是调用操作(SQL同义词)。

因此,在这种情况下,我们将创建一个SQL同义词并将其部署到每个客户,该SQL同义词具有effective_rate引用该effective_rate_default过程的名称。当然,Cust1仅此同义词必须不引用默认过程,而是引用Cust1变体。但是,正如我已经提到的,我们在源代码管理中仅维护一个数据库,而在Trunk(以及任何发行分支)中,每个同义词始终仅引用相关操作的默认实现。那么我们如何实现这一目标呢?

答案是一个两阶段的部署过程。第一阶段向每个客户部署effective_rate_default过程以及effective_rate引用该过程的同义词。第二阶段仅将过程部署到Cust1 ,然后在Cust1数据库中删除同义词,并创建一个引用的新过程。

effective_rate_cust1effective_rateeffective_rate_cust1

通过遵循这种方法,基于对每个客户的SQL同义词和两阶段部署过程,我们可以在一个开发数据库中包含所需的专用例程,因此仍然可以为我们的客户提供代码,考虑到不同的业务和合规性要求。

让我们看看如何使用SQL Compare命令行实现此两阶段部署过程。

使用SQL比较的2阶段部署

我们将在简化的部署示例中稍作扩展,并假设有三个客户(Cust1,Cust2和Cust3)都需要定制“有效率”算法的变体。

部署过程的第一阶段将生成一个部署脚本,该脚本将交付给每个客户数据库并在每个客户数据库上运行。这将使所有通用数据库例程(即,没有名称以客户别名结尾的任何例程)升级到相同版本。

第二阶段生成零个或多个特定于客户的同步脚本,这些脚本仅创建或更新特定于该客户的SQL例程,这意味着任何例程的名称都以该用户的别名结尾,在这种情况下,cust1,cust2或cust3。它还将删除并重新创建任何同义词,在本例中为effective_rate同义词,以便每个人始终绑定到正确的基础实现。

为了满足这些要求,我们对所需的每个同步脚本执行一次SQL比较命令行。

阶段1:生成常规部署脚本

在部署过程的第一阶段,我们只执行一次SQL Compare CL,并通过提供一个名为“ shared.xml ” 的XML argfile,传入指示其比较哪些数据库以及如何进行比较的所有参数:

“%programfiles(x86)%\ Red Gate \ SQL Compare 13 \ sqlcompare” /Argfile:"shared.xml“

我在上一篇文章中解释了此Argfile的基本内容,但重要的一点是,首先,它是直接从源代码控制位置比较数据库的两个即时点版本,即新版本和先前版本。 ,其次包括对相应过滤器文件(shared.scpf)的引用。此过滤器文件使用如下所示的过滤器表达式排除任何特定于客户的模式对象版本(在这种情况下,任何以Cust1,Cust2或Cust3结尾的版本):

(@NAME NOT LIKE '%[_]cust1') AND (@NAME NOT LIKE '%[_]cust2') AND (@NAME NOT LIKE '%[_]cust3')

当然,如果您的客户别名全部遵循标准模式(如本简化示例中的做法),则可以使用更通用的过滤器,例如(@NAME NOT LIKE' %[_]cust[0-9]')。但是,我们所有的真实客户名称都不相同,因此不可能进行这种模式匹配。

结果,SQL Compare将生成一个SQL同步脚本,该脚本将仅创建effective_rate_default存储过程,然后删除该effective_rate同义词,然后重新创建该同义词,以使其引用默认过程(CREATE SYNONYM effective_rate FOR effective_rate_default)。

阶段2:生成客户特定的部署脚本

实际上,对于每个客户,此阶段包括两个部分:

  1. SQL Compare自动生成一个脚本,该脚本将创建或修改所需的特定于客户的例程

  2. 我们“重置”每个客户数据库中的所有同义词,以便它们引用正确的基础实现(存储过程或函数等)。为此,我们将所需的代码“注入”到每个自动生成的自定义脚本的末尾

我们针对需要自定义代码的每个客户再次执行SQL Compare CL,只需简单地每次切换argfile即可指示SQL Compare 仅包含名称以该客户的别名结尾的对象。我们将所有客户别名的列表存储在开发数据库中。

“%programfiles(x86)%\ Red Gate \ SQL比较13 \ sqlcompare” /Argfile:"cust1.xml“
“%programfiles(x86)%\ Red Gate \ SQL比较13 \ sqlcompare” /Argfile:"cust2.xml“
“%programfiles(x86)%\ Red Gate \ SQL比较13 \ sqlcompare” /Argfile:"cust3.xml“

每个argfile的内容与shared.xml文件的内容几乎相同,唯一的区别是每个特定于客户的argfile包含对该客户的过滤器文件的引用(例如Cust1.scpf),该引用指示SQL Compare CL使用以下表达式,仅检测特定于该客户的更改

(@NAME LIKE '%[_]cust1')

当比较运行时(例如对于Cust1),SQL Compare将生成一个部署脚本,该脚本将创建,修改或删除*_cust1代表Cust1已安装版本的主干分支中的任何对象,因此它将与源代码控制中的最新版本同步。在这种情况下,它将创建effective_rate_cust1存储过程。

但是,SQL Compare为每个客户自动生成的部署脚本不会将当前的effective_rate同义词(通过在阶段1中运行通用脚本创建)替换为引用effective_rate_cust1存储过程的同义词,因为该同义词在Trunk或任何单个分支中对于每个主要版本(v241,v242等),始终引用默认实现。

因此,每次SQL Compare自动生成特定于客户的同步脚本时,我们都需要对其进行修改,以“重置”脚本中的任何同义词,以便它引用相关操作的特定于特定于客户的实现,或者如果不再需要自定义变体,则恢复为默认操作。

我们不能为此使用标准的SQL Compare部署后脚本,首先,因为当直接与源代码控制位置进行比较时,该工具当前不支持使用它们。无论如何,由于我们简单的“每个发布一个分支”策略,我们无法动态地为每个客户生成部署后脚本,也无法更改每个脚本中的同义词以引用正确的客户实现。使其起作用的唯一方法是使用“每个版本的每个客户变体一个分支”的更复杂的构建方案,将每个分支脚本化到一个文件夹中,然后向其中添加一个后部署脚本,以为此重置同义词。

但是,我们更喜欢使用更简单的源代码控制方法,那么我们该怎么做呢?当SQL Compare将特定于客户的同步文件写入我们选择的目录(由该out客户的XML argfile中的参数指定)时,我们将使用一个本地工具将其打开,并在自动生成的代码的末尾添加一行,以执行我们编写的存储过程称为switch_synonyms_to_customer。此过程接受组织的别名的参数(应将同义词绑定到该参数),然后遍历所有SQL同义词,将它们逐个删除,然后使用同义词引用的基础对象的适当名称重新创建它们。默认值或专用例程(如果特定客户需要)。

因此,对于cust1:

EXEC altasoft.switch_synonyms_to_customer @alias = 'cust1'

对于cust2:

EXEC altasoft.switch_synonyms_to_customer @alias = 'cust2'

等等…

为每个客户运行部署

我们向每个客户提供用于部署所有公共对象的常规部署脚本,并且,如果需要,我们还为每个客户提供为其定制逻辑提供的其他自定义部署脚本,该脚本还将正确重置所有同义词。他们必须始终始终先运行常规脚本,只有完成后才运行其自定义脚本。

如果您正在为许多不同的客户开发数据库应用程序,那么您的客户的需求将开始出现分歧,并且单个部署无法满足您的需求。毕竟,当地的税收和法律以及不同的商业惯例将决定客户如何计算某些财务价值。

为了将所需逻辑中的所有变体仅提供给需要它的客户,SQL Compare命令行可以完成99%的工作。它会生成一个通用同步脚本,以部署每个客户所需的从发行到发行的任何更改,然后针对具有“特殊”要求的每个客户生成单独的同步脚本文件。

通过使用同义词表示每个必需的业务操作,并在每个特定于客户的同步脚本的末尾“手动”重置它们,以便它们始终引用此操作的正确实现,我们避免了对调用者进行任何更改码。

在每个发行版中,都有可能为客户创建了一些新逻辑,或者更新了现有的自定义逻辑或将其删除。如果某些操作不再需要自定义实现,则将其删除,因此客户将返回该操作的默认实现。

上述就是小编为大家分享的SQL Compare怎样使用SQL比较命令行从源代码管理中进行自定义部署了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI