您是否将数据库静态数据放入源代码控制中?怎么样?

时间:2009-10-06 13:27:24

标签: sql version-control

我正在使用SQL-Server 2008和Visual Studio Database Edition。

通过此设置,保持架构同步非常简单。基本上,有一个“比较模式”工具,允许我将两个数据库和/或数据库模式的模式与源控制的创建脚本文件夹同步。

然而,就数据而言,情况不太清楚,数据可能有三种不同:

  • 代码中引用的静态数据。典型示例:我的用户可以更改其设置,并将其配置存储在服务器上。但是,如果用户没有覆盖它,则每个设置都有一个系统范围的默认值。包含这些默认设置的表随着向程序添加更多选项而增长。这意味着当签入新功能/选项时,通常也会在数据库中创建系统范围的默认设置。

  • 静态数据。例如。填充下拉列表的产品列表。该程序不依赖列表中特定产品的存在来工作。例如,这可以是在部署程序的新“unicode版本”时应在生产中部署的unicode编码产品列表。

  • 其他数据,即其他所有内容(日志,用户帐户,用户数据等)

我觉得我的第三项不应该是源控制的(当然,它应该定期备份)

但是关于静态数据,我想知道该怎么做。

  • 我应该将插入脚本附加到创建脚本吗?或者可以使用单独的脚本?

  • 我(作为开发人员)如何警告执行部署的人员应该执行插入语句?

  • 我应该区分我的两种数据吗? (第一个通常由开发人员创建,而第二个通常由非开发人员创建)

如何管理数据库静态数据?

9 个答案:

答案 0 :(得分:7)

我已经解释了我在博客Version Control and Your Database中使用的技术。我使用数据库元数据(在本例中为SQL Server扩展属性)来存储已部署的应用程序版本。我只有从版本升级到版本的脚本。在启动时,应用程序从数据库元数据中读取已部署的版本(缺少元数据被解释为版本0,即尚未部署任何内容)。对于每个版本,都有一个应用程序功能,可以升级到下一个版本。通常,此函数运行执行升级的内部资源T-SQL脚本,但它可能是其他内容,例如在数据库中部署CLR程序集。

没有用于部署“当前”数据库架构的脚本。新版本将从版本1到当前版本的所有中间版本进行迭代。

我喜欢这种技术有几个优点:

  • 我很容易测试新版本。我有以前版本的备份,我应用升级脚本,然后我可以恢复到以前的版本,更改脚本,再试一次,直到我对结果满意为止。
  • 我的应用程序可以部署在任何以前的版本之上。各种客户端都有各种部署版本。升级后,我的应用程序支持从任何先前版本升级。
  • 全新安装和升级之间没有区别,它运行相同的代码,因此我维护和测试的代码路径较少。
  • DML和DDL更改之间没有区别(您的原始问题)。他们都以同样的方式对待,因为脚本运行从一个版本更改为下一个版本。当我需要像您描述的那样进行更改(更改默认值)时,即使没有发生其他DDL更改,我实际上也会增加模式版本 。所以在版本5.1中默认为'foo',在5.2中默认为'bar',这是两个版本之间的唯一区别,而'upgrade'步骤只是一个UPDATE语句(紧随其后)当然是通过版本元数据更改,即.sp_updateextendedproperty)。
  • 所有更改都在源代码管理中,部分是应用程序源(主要是T-SQL脚本)。
  • 我可以轻松访问任何以前的架构版本,例如。重新调整客户投诉,只需运行升级程序并停在我感兴趣的版本上。

这种方法多次拯救了我的皮肤,现在我是一个真正的信徒。只有一个缺点:在源代码中没有明显的地方可以找到“foo的当前形式是什么?”。因为最新版本的foo可能已经升级了2或3个版本并且之后没有更改,所以我需要查看那个版本的升级脚本。我通常只是查看数据库并查看其中的内容,而不是搜索升级脚本。

最后一点:这实际上不是我的发明。这完全取决于SQL Server自身如何升级数据库元数据(mssqlsystemresource)。

答案 1 :(得分:2)

如果要更改静态数据(将新项添加到用于生成下拉列表的表),则插入应位于源代码管理中,并与其余代码一起部署。如果其他代码需要插入工作,则尤其如此。否则,在部署代码时可能会忘记此步骤,而不会发生这么好的事情。

如果静态数据来自其他来源(例如在美国导入当前的机场代码),那么您可能只需要运行已经记录的导入过程。导入过程本身应该在源代码控制中(我们使用所有SSIS包执行此操作),但数据不必是。

答案 2 :(得分:2)

在Red Gate,我们最近在SQL Data Compare中添加了一项功能,允许将静态数据存储为DML(每个表一个.sql文件)以及SQL Compare当前支持的架构DDL。

了解其工作原理,here is a diagram解释其工作原理。

我们的想法是,当您想要将更改推送到目标服务器时,可以使用脚本作为源数据源进行比较,从而生成必要的DML同步脚本以更新目标。这意味着您不必假设每次都从头开始重新创建目标。我们希望在即将到来的SQL Source Control tool中支持静态数据。

Red Gate Software产品经理David Atkinson

答案 3 :(得分:1)

我非常喜欢你对三种数据的区分。

我同意第三

在我们的应用程序中,我们尽量避免在数据库中放入第一个,因为它是重复的(因为它必须在代码中,数据库是重复的)。第二个好处是我们不需要连接或查询来从代码中访问该值,因此这会加快速度。

  

如果我们希望在数据库中有其他信息,例如,如果可以按客户站点更改,我们将两者分开。其他表仍然可以引用该数据(通过索引ex:0,1,2,3或代码ex:EMPTY,SIMPLE,DOUBLE,ALL)。

对于 second ,脚本应该在源代码控制中。我们将它们与结构分开(我认为它们通常会随着时间的推移而被替换,而结构会不断添加增量)。


  

我(作为开发人员)如何警告执行部署的人员应该执行插入语句?

我们有一个完整的程序,每个版本附带自述文件,脚本等等......

答案 4 :(得分:1)

我在开发CMS系统时遇到过这种情况。

我将静态数据(代码中引用的内容)附加到数据库创建脚本,然后添加一个单独的脚本以添加任何“初始化数据”(如国家,初始产品群等)。

答案 5 :(得分:1)

对于前两个步骤,您可以考虑对数据使用中间格式(即XML),然后使用自行开发的工具或CodeSmith之类的东西来生成SQL,以及可能的源文件,如果(对于例如,您有与代码中使用的枚举相关的查找表 - 这有助于实现一致性。

这有另一个好处,如果架构发生更改,在许多情况下您不必重新生成所有INSERT语句 - 只需更改工具即可。

答案 6 :(得分:1)

this thread's answer。前两点的静态数据应该在源代码管理中,恕我直言。

编辑:*新

  • 一体化或单独的脚本?只要您(开发团队)同意您的部署团队,这并不重要。我更喜欢分开文件,但我仍然可以按照正确的顺序创建all-in-one.sql [Logins, Roles, Users; Tables; Views; Stored Procedures; UDFs; Static Data; (Audit Tables, Audit Triggers)]
  • 如何确保执行:好吧,在应用程序/数据库部署文档中再迈出一步。如果您在数据库中推出真正需要特定(新)静态数据的应用程序,那么您可能希望在应用程序中执行数据库版本检查。并将DB_VERSION更新为新版本号,作为该脚本的一部分。然后,如果需要新的数据库版本,启动时的应用程序应检查并报告错误。
  • dev和非开发静态数据:我从未见过这种情况。更常见的是真实静态数据,您可以将其称为“dev”,这是主要配置,ISO静态数据等。另一种类型是默认查找数据,这是用户可以从那里开始,但他们可能会添加更多。 INSERT这些数据的机制可能有所不同,因为您需要确保不会使用户创建的数据失去动力。

答案 7 :(得分:1)

首先,我从未使用过Visual Studio Database Edition。使用此实用程序为您提供的任何工具,您都是幸运的(或被诅咒)。希望这包括很多灵活性。

我不知道我会在你的1型和2型静态数据之间做出很大的改变。两者都是定义一次然后永不更新的数据集,除非后续版本和更新,对吧?在这种情况下,主要区别在于数据是如何或为何原样,而不是如何存储或初始化数据。 (除非数据是特定于环境的,如用于开发的“A”,用于生产的“B”。这将是“类型4”数据,我将在这篇文章中高兴地忽略它,因为我已经使用SQLCMD解决了它变量,他们让我头疼。)

首先,我将创建一个脚本来创建数据库中的所有表 - 最好只有一个脚本,否则你可以有很多脚本(当重命名列时查找和替换变得非常笨拙)。然后,我会创建一个脚本来填充这些表中的静态数据。此脚本可以附加到表脚本的末尾,或者使其成为自己的脚本,甚至可以为每个表创建一个脚本,如果要加载数百或数千行,这是一个好主意。 (有些人制作一个csv文件,然后发出一个BULK INSERT,但我会避免这只是给你两个文件和一个复杂的过程[在部署时配置驱动器映射]来管理。)

要记住的关键是数据(存储在数据库中)可以并且会随着时间而改变。很少(如果有的话)你会很幸运地删除你的生产数据库,并用一个新的,有光泽的新数据库替换它,没有过去十年来所有那些狡猾的数据。数据库都是关于随时间的变化,而这正是脚本自成一体的地方。您可以从脚本开始创建数据库,然后随着时间的推移添加修改数据库的脚本 - 这也适用于您的静态数据(任何类型)。

(最终,我的方法类似于会计:你有账户,随着变化的到来你用日记账分录调整账户。如果你发现你犯了错误,你再也不会回去修改你的参赛作品,你只需要后续条目可以反转并修复它们。这只是一个类比,但逻辑是合理的。)

答案 8 :(得分:1)

我使用的解决方案是在源代码管理中创建和更改脚本,以及存储在数据库中的版本信息。

然后,我有一个安装向导,可以检测是否需要创建或更新数据库 - 通过根据数据库中存储的版本信息选择适当的脚本来管理更新过程。