I am part of a development team currently working with a database that does not have any kind of source control. We work with SQL Server 2008 R2 and have always managed the DB directly with SSMS. It now has ~340 tables and ~1600 stored procedures, plus a few triggers and views, so it is not a small DB.
我是一个开发团队的一员,目前正在使用一个没有任何源代码控制的数据库。我们使用SQL Server 2008 R2并始终使用SSMS直接管理数据库。它现在有~340个表和~1600个存储过程,加上一些触发器和视图,所以它不是一个小DB。
My goal is to have the DB under version control, so I have been reading articles, like Scott Allen's series and many old SO related questions. But I am still unable to decide on how to proceed.
我的目标是让数据库处于版本控制之下,所以我一直在阅读文章,比如Scott Allen的系列文章以及许多旧的SO相关问题。但我仍然无法决定如何继续。
What I'm thinking of is to script the database schema in one file, then procedures, triggers and views in one file each. Then keep everything versioned under Mercurial. But of course, every member of the team can access SSMS and directly change the schema and procedures, with the possibility that any of us can forget to replicate those changes in the versioned files.
我想到的是在一个文件中编写数据库模式脚本,然后在每个文件中编写过程,触发器和视图。然后将所有版本都保存在Mercurial下。但是,当然,团队的每个成员都可以访问SSMS并直接更改模式和过程,我们中的任何人都可能忘记在版本化文件中复制这些更改。
What better options are there? And, did I forget any element worth having source control of? My biggest concern is that most of the literature I found explains how to do version control when creating a new database, but not when it is already old and relatively big.
还有哪些更好的选择?而且,我是否忘记了任何值得拥有源代码控制权的元素?我最关心的是我发现的大多数文献都解释了在创建新数据库时如何进行版本控制,但是当它已经陈旧且相对较大时。
5 个解决方案
#1
14
The General Process
一般过程
We create a baseline for a particular version (say, v1.0
). A baseline includes one complete schema creation script, as well an upgrade script from allowed previous versions, if any (more on that in a moment). So for v1.0
, we'd have just one script:
我们为特定版本(例如,v1.0)创建基线。基线包括一个完整的模式创建脚本,以及允许的先前版本的升级脚本(如果有的话)(稍后会详细介绍)。所以对于v1.0,我们只有一个脚本:
baseline-v1.0.sql
From that baseline, we create incremental change scripts as we work from the previous baseline. These scripts are created in a way that they are reentrant, so that they can be run safely multiple times (where the first time only does any actual work; see the next paragraph on a suggestion how). We just create a file for each change script with the baseline name and a timestamp (which we call the version). So for example, say we create two change scripts after a baseline. We'd have the following files:
从该基线开始,我们在从前一个基线开始工作时创建增量更改脚本。这些脚本以可重入的方式创建,以便它们可以安全地多次运行(第一次只执行任何实际工作;请参阅下一段有关建议的方法)。我们只为每个更改脚本创建一个文件,其中包含基线名称和时间戳(我们称之为版本)。例如,假设我们在基线之后创建了两个更改脚本。我们有以下文件:
baseline-v1.0.sql (for creating new installations)
baseline-v1.0-201211071220.sql (created on Nov. 7, 2012 at 12:20 PM UTC)
baseline-v1.0-201211122019.sql (created on Nov. 12, 2012 at 8:00 PM UTC)
We create a schema_version
table that has two columns: baseline
and version
. baseline
is some label (such as v1.0
mentioned above), and version
is just a timestamp of when the change script was created (we chose to do this because creating arbitrary version numbers created annoying administrative overhead, where a timestamp was easy to use). So before running the change script, we check to see if the change script has been applied yet, by querying for it by baseline
and version
. If it's already present, just return out of the script or whatever. Otherwise, apply the change and insert into the schema_version
table to mark the change script completed.
我们创建一个schema_version表,它有两列:baseline和version。 baseline是一些标签(例如上面提到的v1.0),而version只是创建更改脚本的时间戳(我们选择这样做是因为创建任意版本号会产生令人讨厌的管理开销,其中时间戳很容易使用)。因此,在运行更改脚本之前,我们通过基线和版本查询来检查更改脚本是否已应用。如果已经存在,只需退出脚本或其他任何内容。否则,应用更改并插入schema_version表以标记更改脚本已完成。
Example change script:
示例更改脚本:
-- Created by <developer> on Nov. 7, 2012 at 12:20 PM UTC
declare @schema_baseline varchar(10), @schema_version varchar(12)
set @schema_baseline = 'v1.0'
set @schema_version = '201211071210'
if exists (select 1 from schema_version where baseline = @schema_baseline and version = @schema_version = @schema_version) return 0
-- begin change script
-- place your schema changes here
-- end change script
insert into schema_version(@schema_baseline, @schema_version)
Now, when we actually install the software, we run the relevant baseline
script. As we upgrade that version, we just apply the change scripts in order.
现在,当我们实际安装软件时,我们运行相关的基线脚本。在我们升级该版本时,我们只是按顺序应用更改脚本。
When we hit a significant milestone in our product development phase, we create a new baseline. So, we create a new baseline script (again, this is a snapshot of the DB as a baseline), plus an upgrade script from the previous baseline. So let's say we have a new baseline, v2.0
, we'd have the following files:
当我们在产品开发阶段达到一个重要的里程碑时,我们会创建一个新的基线。因此,我们创建一个新的基线脚本(同样,这是数据库作为基线的快照),以及上一个基线的升级脚本。所以假设我们有一个新的基线,v2.0,我们有以下文件:
baseline-v2.0.sql (for creating new installations)
baseline-v2.0-upgrade-v1.0.sql (for upgrading from v1.0)
Then the process continues.
然后该过程继续。
How We Apply Changes
我们如何应用变更
The scripts are all kept in source control. We do have a tool that packages these files and automatically upgrades databases, which our support and installation teams use. The tool figures out the current baseline of the target database, and asks the user if they wish to upgrade to the baseline in the package. If they do, and there is a valid upgrade path from the current version, it applies the upgrade script, and updates the schema_version.baseline
, and deletes all entries for change scripts from the previous baseline. If the database is new, it applies the regular baseline script. Either way, after the baseline is achieved, it applies all change scripts from the baseline that are present in the package, one at a time, in order, in a transaction. If a particular change script fails, it rolls back the last set of changes and errors out. We look at the log, fix any issues, then rerun the package again. At that point, it should just pick up at the last change script that succeeded, saving time.
这些脚本都保存在源代码管理中。我们有一个工具可以打包这些文件并自动升级我们的支持和安装团队使用的数据库。该工具计算出目标数据库的当前基线,并询问用户是否希望升级到包中的基线。如果这样做,并且当前版本存在有效的升级路径,则它将应用升级脚本,并更新schema_version.baseline,并从先前的基准中删除更改脚本的所有条目。如果数据库是新的,则它应用常规基线脚本。无论哪种方式,在实现基线之后,它会在事务中按顺序应用程序包中存在的基线中的所有更改脚本。如果特定更改脚本失败,则会回滚最后一组更改和错误。我们查看日志,修复任何问题,然后重新运行包。此时,它应该只是在最后一个成功的更改脚本中获取,从而节省时间。
Automation and Diff Tools
自动化和差异工具
We do not allow diff tools to upgrade production databases directly. It's just too risky. We do use diff tools, of course, to help create our upgrade and change scripts, but once we have them, we comb through them, massage them, test them, etc., then create the upgrade or change script according to the specs above. We do use tools/shell scripts to create the change script files and put the boiler plate schema_version
checking.
我们不允许diff工具直接升级生产数据库。这太危险了。当然,我们使用diff工具来帮助创建我们的升级和更改脚本,但是一旦我们拥有它们,我们梳理它们,按摩它们,测试它们等,然后根据上面的规范创建升级或更改脚本。我们使用工具/ shell脚本来创建更改脚本文件并将锅炉板schema_version检查。
Caveats
注意事项
It's actually pretty straight-forward and it works well. The only time it really gets tricky is with branches. For the most part, branches are handled well. If we need a change script for a particular branch's work, it will fold into the mainline very well once we merge the branch back in. No problem. Where it gets tricky is when two branches try to do similar things, or where one branch relies on another. That's mostly a process and planning issue, though. If we get stuck in such a situation, we just create a new baseline (say v2.1
), then update the branches accordingly.
它实际上非常简单,而且效果很好。它唯一真正变得棘手的是分支机构。在大多数情况下,分支机构处理得很好。如果我们需要一个特定分支工作的更改脚本,一旦我们将分支合并回来,它将很好地折叠到主线。没问题。它变得棘手的地方是两个分支尝试做类似的事情,或者一个分支依赖另一个分支。但这主要是一个过程和计划问题。如果我们陷入这种情况,我们只需创建一个新基线(比如v2.1),然后相应地更新分支。
Another thing to keep in mind is if an installation wants to be upgraded from one baseline to another, it has to apply all outstanding changes for the current baseline, before we upgrade to the new one. In other words, we don't let installations jump right from where ever they are to the next baseline (unless, of course, they're already at the most recent version for the current baseline).
要记住的另一件事是,如果安装想要从一个基线升级到另一个基线,则必须在升级到新基线之前应用当前基线的所有未完成的更改。换句话说,我们不会让安装从它们的任何位置直接跳到下一个基线(当然,除非它们已经是当前基线的最新版本)。
#2
11
I would recommend SQL Server Data Tools and/or a Visual Studio SQL database project. It will reverse engineer your existing DB to code(sql) files that can be version controlled and gives many other niceties (publishing, comparison, etc)
我建议使用SQL Server数据工具和/或Visual Studio SQL数据库项目。它会将您现有的数据库反向工程为可以进行版本控制的代码(sql)文件,并提供许多其他细节(发布,比较等)
#3
5
We developed SQL Source Control specifically to solve the problem you describe. It extends SSMS to provide a link between your SQL Server schema objects (and static data) and your existing source control system.
我们专门开发了SQL Source Control来解决您描述的问题。它扩展了SSMS,以提供SQL Server架构对象(和静态数据)与现有源代码控制系统之间的链接。
http://www.red-gate.com/products/sql-development/sql-source-control/
http://www.red-gate.com/products/sql-development/sql-source-control/
If you need any more information, we'd be very pleased to help (contact support@red-gate.com)
如果您需要更多信息,我们非常乐意提供帮助(联系support@red-gate.com)
#4
2
There have been many discussions regarding this topic on many developer forums.
在许多开发者论坛上有很多关于这个主题的讨论。
What I have done and found to be the simplest and cleanest way to do is this:
我所做的并被发现是最简单,最干净的方法是:
-
Extract every DB object's DDL into its own file, indexes and PKs can go in the same file as the table they belong to. FKs, procedures, views, triggers, anything that can go across multiple tables go in their own file.
将每个数据库对象的DDL解压缩到自己的文件中,索引和PK可以与它们所属的表位于同一个文件中。 FK,过程,视图,触发器,可以跨多个表的任何内容都放在他们自己的文件中。
-
Organize the DDL files in dirs per object type (e.g. table, procedure, trigger, view etc.)
按目标类型的dirs组织DDL文件(例如表,过程,触发器,视图等)
-
For tables holding static reference data (e.g. zip code or state), have a separate file with a bunch of insert statements
对于包含静态引用数据(例如邮政编码或状态)的表,请使用带有一堆insert语句的单独文件
-
Check this directory structure into whatever version control you are using
将此目录结构检查到您正在使用的任何版本控件
-
Write a script that will traverse this directory structure that images your DB, diff it against the actual DB you point to (extracting the schema from the system tables) and apply the diffs using ALTER TABLE statements
编写一个脚本,遍历这个映像数据库的目录结构,将其与您指向的实际数据库进行区分(从系统表中提取模式)并使用ALTER TABLE语句应用差异
-
In case you have data transformations between releases, e.g. in v1 you had a field FirstAndLastName and in v2 you decided to split it into FirstName and LastName, you will have some bulk data migration/processing statement.
如果您在版本之间进行数据转换,例如在v1中你有一个字段FirstAndLastName而在v2中你决定将它拆分为FirstName和LastName,你将有一些批量数据迁移/处理语句。
I have successfully managed DB changes in several jobs using several different RDBMSs. I usually use Perl for the script that diffs the DB schema and the DDL files in your image. There are some assumptions to this method and one of them is that you never make any changes to the DB directly in the DB but in your DDL files and then run the script to apply it. If you do it the other way, they will be undone when you run the script. So it requires some team agreement and discipline. Your milage may vary.
我已经使用几个不同的RDBMS成功管理了几个作业中的数据库更改。我通常使用Perl作为差异DB模式和图像中DDL文件的脚本。这个方法有一些假设,其中之一就是你永远不会直接在DB中对DB进行任何更改,而是在DDL文件中,然后运行脚本来应用它。如果以其他方式执行此操作,则在运行脚本时将撤消它们。所以它需要一些团队协议和纪律。你的milage可能会有所不同。
Now, if there is a FOSS tool out there that will do this for you, by all means use that rather than devising your own. I've been doing things this way for more than 10 yrs
现在,如果有一个FOSS工具会为你做这件事,一定要用它而不是设计你自己的。我已经用这种方式做了10多年
#5
0
Our Sql Historian source control system can help folks with this problem, especially in the situation you mention where teammates"forget" to check in code after they've updated the server.
我们的Sql Historian源代码控制系统可以帮助解决这个问题的人,特别是在你提到的情况下,队友们在更新服务器后“忘记”检查代码。
It sits in the background and records all changes made to your db objects into source control, without users needing to check anything in. Think of it like an airplane blackbox recorder, staying out of the way until you need it.
它位于后台,并将对数据库对象所做的所有更改记录到源代码控制中,无需用户检查任何内容。可以将其视为飞机黑盒记录器,直到需要它为止。
#1
14
The General Process
一般过程
We create a baseline for a particular version (say, v1.0
). A baseline includes one complete schema creation script, as well an upgrade script from allowed previous versions, if any (more on that in a moment). So for v1.0
, we'd have just one script:
我们为特定版本(例如,v1.0)创建基线。基线包括一个完整的模式创建脚本,以及允许的先前版本的升级脚本(如果有的话)(稍后会详细介绍)。所以对于v1.0,我们只有一个脚本:
baseline-v1.0.sql
From that baseline, we create incremental change scripts as we work from the previous baseline. These scripts are created in a way that they are reentrant, so that they can be run safely multiple times (where the first time only does any actual work; see the next paragraph on a suggestion how). We just create a file for each change script with the baseline name and a timestamp (which we call the version). So for example, say we create two change scripts after a baseline. We'd have the following files:
从该基线开始,我们在从前一个基线开始工作时创建增量更改脚本。这些脚本以可重入的方式创建,以便它们可以安全地多次运行(第一次只执行任何实际工作;请参阅下一段有关建议的方法)。我们只为每个更改脚本创建一个文件,其中包含基线名称和时间戳(我们称之为版本)。例如,假设我们在基线之后创建了两个更改脚本。我们有以下文件:
baseline-v1.0.sql (for creating new installations)
baseline-v1.0-201211071220.sql (created on Nov. 7, 2012 at 12:20 PM UTC)
baseline-v1.0-201211122019.sql (created on Nov. 12, 2012 at 8:00 PM UTC)
We create a schema_version
table that has two columns: baseline
and version
. baseline
is some label (such as v1.0
mentioned above), and version
is just a timestamp of when the change script was created (we chose to do this because creating arbitrary version numbers created annoying administrative overhead, where a timestamp was easy to use). So before running the change script, we check to see if the change script has been applied yet, by querying for it by baseline
and version
. If it's already present, just return out of the script or whatever. Otherwise, apply the change and insert into the schema_version
table to mark the change script completed.
我们创建一个schema_version表,它有两列:baseline和version。 baseline是一些标签(例如上面提到的v1.0),而version只是创建更改脚本的时间戳(我们选择这样做是因为创建任意版本号会产生令人讨厌的管理开销,其中时间戳很容易使用)。因此,在运行更改脚本之前,我们通过基线和版本查询来检查更改脚本是否已应用。如果已经存在,只需退出脚本或其他任何内容。否则,应用更改并插入schema_version表以标记更改脚本已完成。
Example change script:
示例更改脚本:
-- Created by <developer> on Nov. 7, 2012 at 12:20 PM UTC
declare @schema_baseline varchar(10), @schema_version varchar(12)
set @schema_baseline = 'v1.0'
set @schema_version = '201211071210'
if exists (select 1 from schema_version where baseline = @schema_baseline and version = @schema_version = @schema_version) return 0
-- begin change script
-- place your schema changes here
-- end change script
insert into schema_version(@schema_baseline, @schema_version)
Now, when we actually install the software, we run the relevant baseline
script. As we upgrade that version, we just apply the change scripts in order.
现在,当我们实际安装软件时,我们运行相关的基线脚本。在我们升级该版本时,我们只是按顺序应用更改脚本。
When we hit a significant milestone in our product development phase, we create a new baseline. So, we create a new baseline script (again, this is a snapshot of the DB as a baseline), plus an upgrade script from the previous baseline. So let's say we have a new baseline, v2.0
, we'd have the following files:
当我们在产品开发阶段达到一个重要的里程碑时,我们会创建一个新的基线。因此,我们创建一个新的基线脚本(同样,这是数据库作为基线的快照),以及上一个基线的升级脚本。所以假设我们有一个新的基线,v2.0,我们有以下文件:
baseline-v2.0.sql (for creating new installations)
baseline-v2.0-upgrade-v1.0.sql (for upgrading from v1.0)
Then the process continues.
然后该过程继续。
How We Apply Changes
我们如何应用变更
The scripts are all kept in source control. We do have a tool that packages these files and automatically upgrades databases, which our support and installation teams use. The tool figures out the current baseline of the target database, and asks the user if they wish to upgrade to the baseline in the package. If they do, and there is a valid upgrade path from the current version, it applies the upgrade script, and updates the schema_version.baseline
, and deletes all entries for change scripts from the previous baseline. If the database is new, it applies the regular baseline script. Either way, after the baseline is achieved, it applies all change scripts from the baseline that are present in the package, one at a time, in order, in a transaction. If a particular change script fails, it rolls back the last set of changes and errors out. We look at the log, fix any issues, then rerun the package again. At that point, it should just pick up at the last change script that succeeded, saving time.
这些脚本都保存在源代码管理中。我们有一个工具可以打包这些文件并自动升级我们的支持和安装团队使用的数据库。该工具计算出目标数据库的当前基线,并询问用户是否希望升级到包中的基线。如果这样做,并且当前版本存在有效的升级路径,则它将应用升级脚本,并更新schema_version.baseline,并从先前的基准中删除更改脚本的所有条目。如果数据库是新的,则它应用常规基线脚本。无论哪种方式,在实现基线之后,它会在事务中按顺序应用程序包中存在的基线中的所有更改脚本。如果特定更改脚本失败,则会回滚最后一组更改和错误。我们查看日志,修复任何问题,然后重新运行包。此时,它应该只是在最后一个成功的更改脚本中获取,从而节省时间。
Automation and Diff Tools
自动化和差异工具
We do not allow diff tools to upgrade production databases directly. It's just too risky. We do use diff tools, of course, to help create our upgrade and change scripts, but once we have them, we comb through them, massage them, test them, etc., then create the upgrade or change script according to the specs above. We do use tools/shell scripts to create the change script files and put the boiler plate schema_version
checking.
我们不允许diff工具直接升级生产数据库。这太危险了。当然,我们使用diff工具来帮助创建我们的升级和更改脚本,但是一旦我们拥有它们,我们梳理它们,按摩它们,测试它们等,然后根据上面的规范创建升级或更改脚本。我们使用工具/ shell脚本来创建更改脚本文件并将锅炉板schema_version检查。
Caveats
注意事项
It's actually pretty straight-forward and it works well. The only time it really gets tricky is with branches. For the most part, branches are handled well. If we need a change script for a particular branch's work, it will fold into the mainline very well once we merge the branch back in. No problem. Where it gets tricky is when two branches try to do similar things, or where one branch relies on another. That's mostly a process and planning issue, though. If we get stuck in such a situation, we just create a new baseline (say v2.1
), then update the branches accordingly.
它实际上非常简单,而且效果很好。它唯一真正变得棘手的是分支机构。在大多数情况下,分支机构处理得很好。如果我们需要一个特定分支工作的更改脚本,一旦我们将分支合并回来,它将很好地折叠到主线。没问题。它变得棘手的地方是两个分支尝试做类似的事情,或者一个分支依赖另一个分支。但这主要是一个过程和计划问题。如果我们陷入这种情况,我们只需创建一个新基线(比如v2.1),然后相应地更新分支。
Another thing to keep in mind is if an installation wants to be upgraded from one baseline to another, it has to apply all outstanding changes for the current baseline, before we upgrade to the new one. In other words, we don't let installations jump right from where ever they are to the next baseline (unless, of course, they're already at the most recent version for the current baseline).
要记住的另一件事是,如果安装想要从一个基线升级到另一个基线,则必须在升级到新基线之前应用当前基线的所有未完成的更改。换句话说,我们不会让安装从它们的任何位置直接跳到下一个基线(当然,除非它们已经是当前基线的最新版本)。
#2
11
I would recommend SQL Server Data Tools and/or a Visual Studio SQL database project. It will reverse engineer your existing DB to code(sql) files that can be version controlled and gives many other niceties (publishing, comparison, etc)
我建议使用SQL Server数据工具和/或Visual Studio SQL数据库项目。它会将您现有的数据库反向工程为可以进行版本控制的代码(sql)文件,并提供许多其他细节(发布,比较等)
#3
5
We developed SQL Source Control specifically to solve the problem you describe. It extends SSMS to provide a link between your SQL Server schema objects (and static data) and your existing source control system.
我们专门开发了SQL Source Control来解决您描述的问题。它扩展了SSMS,以提供SQL Server架构对象(和静态数据)与现有源代码控制系统之间的链接。
http://www.red-gate.com/products/sql-development/sql-source-control/
http://www.red-gate.com/products/sql-development/sql-source-control/
If you need any more information, we'd be very pleased to help (contact support@red-gate.com)
如果您需要更多信息,我们非常乐意提供帮助(联系support@red-gate.com)
#4
2
There have been many discussions regarding this topic on many developer forums.
在许多开发者论坛上有很多关于这个主题的讨论。
What I have done and found to be the simplest and cleanest way to do is this:
我所做的并被发现是最简单,最干净的方法是:
-
Extract every DB object's DDL into its own file, indexes and PKs can go in the same file as the table they belong to. FKs, procedures, views, triggers, anything that can go across multiple tables go in their own file.
将每个数据库对象的DDL解压缩到自己的文件中,索引和PK可以与它们所属的表位于同一个文件中。 FK,过程,视图,触发器,可以跨多个表的任何内容都放在他们自己的文件中。
-
Organize the DDL files in dirs per object type (e.g. table, procedure, trigger, view etc.)
按目标类型的dirs组织DDL文件(例如表,过程,触发器,视图等)
-
For tables holding static reference data (e.g. zip code or state), have a separate file with a bunch of insert statements
对于包含静态引用数据(例如邮政编码或状态)的表,请使用带有一堆insert语句的单独文件
-
Check this directory structure into whatever version control you are using
将此目录结构检查到您正在使用的任何版本控件
-
Write a script that will traverse this directory structure that images your DB, diff it against the actual DB you point to (extracting the schema from the system tables) and apply the diffs using ALTER TABLE statements
编写一个脚本,遍历这个映像数据库的目录结构,将其与您指向的实际数据库进行区分(从系统表中提取模式)并使用ALTER TABLE语句应用差异
-
In case you have data transformations between releases, e.g. in v1 you had a field FirstAndLastName and in v2 you decided to split it into FirstName and LastName, you will have some bulk data migration/processing statement.
如果您在版本之间进行数据转换,例如在v1中你有一个字段FirstAndLastName而在v2中你决定将它拆分为FirstName和LastName,你将有一些批量数据迁移/处理语句。
I have successfully managed DB changes in several jobs using several different RDBMSs. I usually use Perl for the script that diffs the DB schema and the DDL files in your image. There are some assumptions to this method and one of them is that you never make any changes to the DB directly in the DB but in your DDL files and then run the script to apply it. If you do it the other way, they will be undone when you run the script. So it requires some team agreement and discipline. Your milage may vary.
我已经使用几个不同的RDBMS成功管理了几个作业中的数据库更改。我通常使用Perl作为差异DB模式和图像中DDL文件的脚本。这个方法有一些假设,其中之一就是你永远不会直接在DB中对DB进行任何更改,而是在DDL文件中,然后运行脚本来应用它。如果以其他方式执行此操作,则在运行脚本时将撤消它们。所以它需要一些团队协议和纪律。你的milage可能会有所不同。
Now, if there is a FOSS tool out there that will do this for you, by all means use that rather than devising your own. I've been doing things this way for more than 10 yrs
现在,如果有一个FOSS工具会为你做这件事,一定要用它而不是设计你自己的。我已经用这种方式做了10多年
#5
0
Our Sql Historian source control system can help folks with this problem, especially in the situation you mention where teammates"forget" to check in code after they've updated the server.
我们的Sql Historian源代码控制系统可以帮助解决这个问题的人,特别是在你提到的情况下,队友们在更新服务器后“忘记”检查代码。
It sits in the background and records all changes made to your db objects into source control, without users needing to check anything in. Think of it like an airplane blackbox recorder, staying out of the way until you need it.
它位于后台,并将对数据库对象所做的所有更改记录到源代码控制中,无需用户检查任何内容。可以将其视为飞机黑盒记录器,直到需要它为止。