首页 文章

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

提问于
浏览
18

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

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

但是,对于数据而言,情况不太清楚,数据可能有三种不同:

  • static data referenced in the code . 典型示例:我的用户可以更改其设置,并将其配置存储在服务器上 . 但是,有's a system-wide default value for each setting that is used in case the user didn' t覆盖它 . 包含这些默认设置的表随着向程序添加更多选项而增长 . 这意味着在签入新功能/选项时,通常也会在数据库中创建系统范围的默认设置 .

  • static data . 例如 . 填充下拉列表的产品列表 . 该程序不依赖列表中特定产品的存在来工作 . 例如,这可以是在部署程序的新"unicode version"时应在 生产环境 中部署的unicode编码产品的列表 .

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

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

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

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

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

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

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

9 回答

  • 1

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

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

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

    • 我很容易测试新版本 . 我有以前版本的备份,我应用升级脚本,然后我可以恢复到以前的版本,更改脚本,再试一次,直到我对结果满意为止 .

    • 我的应用程序可以部署在任何以前的版本之上 . 各种客户端都有各种部署版本 . 升级时,我的应用程序支持从任何先前版本升级 .

    • 全新安装和升级之间没有区别,它运行相同的代码,因此我维护和测试的代码路径较少 .

    • DML和DDL更改之间没有区别(您的原始问题) . 他们都以同样的方式对待,因为脚本运行从一个版本更改为下一个版本 . 当我需要像您描述的那样进行更改(更改默认值)时,即使没有发生其他DDL更改,我实际上也会增加架构版本 . 因此,在版本5.1中,默认值是'foo',在5.2中,默认值是'bar',这是两个版本之间的唯一区别,而'upgrade'步骤只是一个UPDATE语句(当然后面是版本元数据更改,即sp_updateextendedproperty) .

    • 所有更改都在源代码管理中,是应用程序源的一部分(主要是T-SQL脚本) .

    • 我可以很容易地获得任何以前的架构版本,例如 . 重新调整客户投诉,只需运行升级序列并停止我感兴趣的版本即可 .

    这种方法多次拯救了我的皮肤,而且'm a true believer now. There is only one disadvantage: there is no obvious place to look in source to find '当前形式的程序foo是什么? '. Because the latest version of foo might have been upgraded 2 or 3 versions ago and it wasn' t发生了变化,我需要查看该版本的升级脚本 . 我通常只是查看数据库并查看其中的内容,而不是搜索升级脚本 .

    最后一点:这实际上不是我的发明 . 这完全是在SQL Server自身升级数据库元数据(mssqlsystemresource)之后建模的 .

  • 7

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

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

  • 1

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

    要了解它是如何工作的,here is a diagram解释了它是如何工作的 .

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

    Red Gate Software产品经理David Atkinson

  • 2

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

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

  • 1

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

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

  • 1

    我非常喜欢你区分三种类型的数据 .

    我同意 third .

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

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

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


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

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

  • 1

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

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

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

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

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

  • 1

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

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

  • 2

    this thread's answer . 来自前两点的静态数据应该在源控制中,恕我直言 .

    *Edit: new

    • all-in-one or a separate script? 只要您(开发团队)同意您的部署团队,这并不重要 . 我更喜欢分开文件,但我仍然可以按照正确的顺序创建all-in-one.sql [Logins, Roles, Users; Tables; Views; Stored Procedures; UDFs; Static Data; (Audit Tables, Audit Triggers)]

    • how do you make sure they execute it :好吧,在应用程序/数据库部署文档中再迈一步 . 如果您在数据库中推出真正需要特定(新)静态数据的应用程序,那么您可能希望在应用程序中执行数据库版本检查 . 并将DB_VERSION更新为新版本号,作为该脚本的一部分 . 然后,如果需要新的数据库版本,启动时的应用程序应检查并报告错误 .

    • dev and non-dev static data :我从未见过这种情况 . 更常见的是 real static data ,您可以将其称为"dev",这是主要配置,ISO静态数据等 . 另一种类型是 default lookup data ,供用户使用,但它们可能会添加更多 . INSERT这些数据的机制可能不同,因为您需要确保不会对用户创建的数据进行驱动(强制) .

相关问题