版本控制SQL Server数据库
我想让我的数据库在版本控制下。 有没有人有任何build议或推荐的文章,让我开始?
我总是希望至less有一些数据在那里(如alumb提到:用户types和pipe理员)。 我还经常需要大量的生成testing数据来进行性能测量。
Martin Fowler写了我最喜欢的文章, http://martinfowler.com/articles/evodb.html 。 我select不要将模式转储放在版本控制下,因为我想要一个简单的方法来升级我的生产数据库。
对于我将有一个生产数据库实例的Web应用程序,我使用两种技术:
数据库升级脚本
包含将模式从版本N移动到N + 1所需的DDL的序列数据库升级脚本。 (这些进入你的版本控制系统。)_version_history_表,类似
create table VersionHistory ( Version int primary key, UpgradeStart datetime not null, UpgradeEnd datetime );
每次升级脚本运行时都会得到一个新的条目,这对应于新版本。
这可以确保很容易地看到数据库模式的版本是否存在以及数据库升级脚本是否只运行一次。 再次,这些不是数据库转储。 相反,每个脚本都代表了从一个版本移动到另一个版本所需的更改 。 它们是您应用于生产数据库“升级”的脚本。
开发人员沙盒同步
- 备份,消毒和收缩生产数据库的脚本。 每次升级到生产数据库后运行此操作。
- 在开发人员的工作站上恢复(并在必要时调整)备份的脚本。 每个开发人员在每次升级到生产数据库后都运行此脚本。
警告:我的自动化testing是针对模式正确但是空的数据库运行的,所以这个build议不会完全适合您的需求。
Red Gate的SQL比较产品不仅允许您进行对象级比较,并从中生成更改脚本,还允许您将数据库对象导出到由对象types组织的文件夹层次结构中,同时创build一个[objectname] .sql脚本每个对象在这些目录中。 对象types层次结构如下所示:
\function
\安全
\安全\angular色
\安全\架构
\安全\用户
\存储过程
\表
如果您在更改后将脚本转储到同一根目录,则可以使用它来更新SVN仓库,并分别保存每个对象的运行历史logging。
这是围绕发展的“难题”之一。 据我所知,没有完美的解决scheme。
如果您只需要存储数据库结构而不是数据,则可以将数据库导出为SQL查询。 (在企业pipe理器中:右键单击数据库 – >生成SQL脚本,我build议在选项卡上设置“为每个对象创build一个文件”)然后你可以将这些文本文件提交到svn,并使用svn的diff和loggingfunction。
我把它和一个带有几个参数的批处理脚本绑定在一起,并build立了数据库。 我还添加了一些额外的查询,input用户types和pipe理员用户的默认数据。 (如果你想要更多的信息,发布一些东西,我可以把脚本放在某个地方)
如果您还需要保留所有的数据,我build议保留数据库的备份,并使用Redgate( http://www.red-gate.com/ )产品进行比较。 他们不便宜,但他们是值得的每一分钱。
首先,您必须select适合您的版本控制系统:
-
集中式版本控制系统 – 一个标准的系统,在这个系统中,用户在处理文件之前/之后检出/检入,并且文件被保存在一个中央服务器上
-
分布式版本控制系统 – 克隆存储库的系统,每个克隆实际上是存储库的完整备份,所以如果任何服务器崩溃,那么可以使用任何克隆的存储库来恢复它。在为您的需求select正确的系统后,您需要设置作为每个版本控制系统核心的存储库。所有这一切都在以下文章中进行了解释: http : //solutioncenter.apexsql.com/sql-server-source-control-part-i-understanding -source -控制-基础/
设置存储库后,如果中央版本控制系统是工作文件夹,则可以阅读本文 。 它展示了如何使用以下代码在开发环境中设置源代码pipe理:
-
SQL Server Management Studio通过MSSCCI提供程序,
-
Visual Studio和SQL Server数据工具
- 第三方工具ApexSQL源代码控制
在Red Gate,我们提供了一个工具SQL Source Control ,它使用SQL比较技术将您的数据库与TFS或SVN存储库连接起来。 这个工具集成到SSMS中,让你像往常一样工作,除了现在让你提交对象。
对于基于迁移的方法(更适合于自动部署),我们提供ReadyRoll ,它将创build和pipe理一组增量脚本作为Visual Studio项目。
在SQL源代码pipe理中,可以指定静态数据表。 这些作为INSERT语句存储在源代码控制中。
如果您正在讨论testing数据,我们build议您使用工具或通过您定义的后期部署脚本来生成testing数据,或者您只需将生产备份恢复到开发环境。
你可能想看看Liquibase( http://www.liquibase.org/ )。 即使你不使用这个工具,它也能很好地处理数据库变更pipe理或重构的概念。
对于推荐使用RedGate工具的每个人+1,附加build议和警告。
SqlCompare也有一个体面的API:所以你可以,例如,编写一个控制台应用程序,同步你的源代码控制的脚本文件夹与CI集成testing数据库签入,以便当有人检查从他们的脚本文件夹架构的变化它会随着匹配的应用程序代码更改而自动部署。 这有助于缩小与忘记将本地数据库中的更改传播到共享开发数据库的开发人员的差距(我们大约有一半人认为:))。
需要注意的是,使用脚本解决scheme或其他方式,RedGate工具足够stream畅,很容易忘记抽象背后的SQL现实。 如果重命名表中的所有列,SqlCompare将无法将旧列映射到新列,并将删除表中的所有数据。 它会产生警告,但我看到有人点击过去。 这里有一个值得一提的点,我认为,你只能自动化数据库版本升级到目前为止 – 抽象是非常有漏洞的。
我们使用DBGhost来pipe理我们的SQL数据库。 然后你把你的脚本在你的版本控制中build立一个新的数据库,它将build立一个新的数据库,或者将任何现有的数据库升级到版本控制中的模式。 这样,您不必担心创build更改脚本(尽pipe您仍然可以这样做,例如,如果要更改列的数据types并需要转换数据)。
使用VS 2010,使用数据库项目。
- 编写你的数据库
- 更改脚本或直接在您的数据库服务器上
- 使用数据>模式比较同步
制作完美的数据库版本解决scheme,使同步数据库变得轻而易举。
使用更改脚本将数据库脚本保存到版本控制中是一种很好的方法,以便您可以升级您拥有的任何一个数据库。 另外,您可能希望保存不同版本的模式,以便您可以创build完整的数据库,而无需应用所有更改脚本。 处理脚本应该是自动的,这样你就不必手动工作。
我认为每个开发人员都有独立的数据库是非常重要的,不要使用共享数据库。 这样开发人员就可以独立于其他开发人员创buildtesting用例和开发阶段。
自动化工具应该有处理数据库元数据的手段,它告诉哪些数据库处于什么样的开发状态,哪些表包含版本控制数据等等。
您没有提及任何有关您的目标环境或约束的细节,因此这可能不是完全适用的……但是如果您正在寻找一种方法来有效地跟踪不断发展的数据库架构,并且不会对使用Ruby,ActiveRecord的迁移就在你的胡同里。
迁移以编程方式使用Ruby DSL定义数据库转换; 每个转换可以应用或(通常)回滚,允许您在任何给定的时间点跳转到不同版本的数据库模式。 定义这些转换的文件可以像任何其他源代码一样检入版本控制。
因为迁移是ActiveRecord的一部分,所以它们通常用于全栈Rails应用程序; 不过,您可以使用独立于Rails的ActiveRecord。 请参阅这里了解更多关于在Rails之外使用AR的迁移的详细处理。
你也可以看看一个迁移解决scheme。 这些允许您在C#代码中指定数据库模式,并使用MSBuild上下滚动您的数据库版本。
我目前正在使用DbUp ,并且运行良好。
每个数据库应该在源代码控制之下。 缺乏的是将所有数据库对象(“configuration数据”)自动脚本化为文件的工具,然后将其添加到任何源代码pipe理系统。 如果您使用的是SQL Server,那么我的解决scheme是在这里: http : //dbsourcetools.codeplex.com/ 。 玩的开心。 – Nathan。
这很简单。
-
当基础项目准备就绪时,您必须创build完整的数据库脚本。 这个脚本被委托给SVN。 这是第一个版本。
-
之后,所有的开发人员创build更改脚本(ALTER …,新表,sprocs等)。
-
当你需要当前版本时,你应该执行所有新的更改脚本。
-
当应用程序被释放到生产,然后你回到1(但是,那么它将成为课程的后续版本)。
南特将帮助您执行这些更改脚本。 🙂
记住。 有纪律的时候一切正常。 每次数据库更改被提交时代码中的相应函数也被提交。
如果你有一个小的数据库,并且你想要整个版本的版本, 这个批处理脚本可能会有所帮助。 它将Subversion中的MSSQL数据库MDF文件分离,压缩和检查。
如果您主要想要对模式进行版本控制,并且只有less量参考数据,则可以使用SubSonic Migrations来处理该数据。 这样做的好处是,您可以轻松地向上或向下迁移到任何特定的版本。
为了使源代码控制系统的转储速度提高一点点,可以使用sysobjects中的版本信息来查看自上次以来哪些对象发生了更改。
安装程序:在每个您希望逐步检查的数据库中创build一个表,以保存上次检查时的版本信息(第一次运行时为空)。 如果要重新扫描整个数据结构,请清除此表。
IF ISNULL(OBJECT_ID('last_run_sysversions'), 0) <> 0 DROP TABLE last_run_sysversions CREATE TABLE last_run_sysversions ( name varchar(128), id int, base_schema_ver int, schema_ver int, type char(2) )
正常运行模式:您可以从这个sql中获取结果,并为您感兴趣的sql脚本生成sql脚本,并将它们放到您select的源代码pipe理中。
IF ISNULL(OBJECT_ID('tempdb.dbo.#tmp'), 0) <> 0 DROP TABLE #tmp CREATE TABLE #tmp ( name varchar(128), id int, base_schema_ver int, schema_ver int, type char(2) ) SET NOCOUNT ON -- Insert the values from the end of the last run into #tmp INSERT #tmp (name, id, base_schema_ver, schema_ver, type) SELECT name, id, base_schema_ver, schema_ver, type FROM last_run_sysversions DELETE last_run_sysversions INSERT last_run_sysversions (name, id, base_schema_ver, schema_ver, type) SELECT name, id, base_schema_ver, schema_ver, type FROM sysobjects -- This next bit lists all differences to scripts. SET NOCOUNT OFF --Renamed. SELECT 'renamed' AS ChangeType, t.name, o.name AS extra_info, 1 AS Priority FROM sysobjects o INNER JOIN #tmp t ON o.id = t.id WHERE o.name <> t.name /*COLLATE*/ AND o.type IN ('TR', 'P' ,'U' ,'V') UNION --Changed (using alter) SELECT 'changed' AS ChangeType, o.name /*COLLATE*/, 'altered' AS extra_info, 2 AS Priority FROM sysobjects o INNER JOIN #tmp t ON o.id = t.id WHERE ( o.base_schema_ver <> t.base_schema_ver OR o.schema_ver <> t.schema_ver ) AND o.type IN ('TR', 'P' ,'U' ,'V') AND o.name NOT IN ( SELECT oi.name FROM sysobjects oi INNER JOIN #tmp ti ON oi.id = ti.id WHERE oi.name <> ti.name /*COLLATE*/ AND oi.type IN ('TR', 'P' ,'U' ,'V')) UNION --Changed (actually dropped and recreated [but not renamed]) SELECT 'changed' AS ChangeType, t.name, 'dropped' AS extra_info, 2 AS Priority FROM #tmp t WHERE t.name IN ( SELECT ti.name /*COLLATE*/ FROM #tmp ti WHERE NOT EXISTS (SELECT * FROM sysobjects oi WHERE oi.id = ti.id)) AND t.name IN ( SELECT oi.name /*COLLATE*/ FROM sysobjects oi WHERE NOT EXISTS (SELECT * FROM #tmp ti WHERE oi.id = ti.id) AND oi.type IN ('TR', 'P' ,'U' ,'V')) UNION --Deleted SELECT 'deleted' AS ChangeType, t.name, '' AS extra_info, 0 AS Priority FROM #tmp t WHERE NOT EXISTS (SELECT * FROM sysobjects o WHERE o.id = t.id) AND t.name NOT IN ( SELECT oi.name /*COLLATE*/ FROM sysobjects oi WHERE NOT EXISTS (SELECT * FROM #tmp ti WHERE oi.id = ti.id) AND oi.type IN ('TR', 'P' ,'U' ,'V')) UNION --Added SELECT 'added' AS ChangeType, o.name /*COLLATE*/, '' AS extra_info, 4 AS Priority FROM sysobjects o WHERE NOT EXISTS (SELECT * FROM #tmp t WHERE o.id = t.id) AND o.type IN ('TR', 'P' ,'U' ,'V') AND o.name NOT IN ( SELECT ti.name /*COLLATE*/ FROM #tmp ti WHERE NOT EXISTS (SELECT * FROM sysobjects oi WHERE oi.id = ti.id)) ORDER BY Priority ASC
注意:如果您在任何数据库中使用非标准归类,则需要使用数据库归类replace/* COLLATE */
。 即COLLATE Latin1_General_CI_AI
因为我们的应用程序必须跨多个RDBMS工作,所以我们使用数据库中立的扭矩格式(XML)将我们的模式定义存储在版本控制中。 我们还以XML格式对我们的数据库的参考数据进行版本控制,如下所示(“关系”是参考表之一):
<Relationship RelationshipID="1" InternalName="Manager"/> <Relationship RelationshipID="2" InternalName="Delegate"/> etc.
然后,我们使用自行开发的工具来生成从数据库版本X到版本X + 1所需的模式升级和参考数据升级脚本。
我们不存储数据库模式,我们将更改存储到数据库。 我们所做的是存储架构更改,以便为任何版本的数据库构build一个更改脚本,并将其应用到我们客户的数据库。 我写了一个数据库实用程序的应用程序,与我们的主要应用程序分布,可以阅读该脚本,并知道哪些更新需要应用。 它也有足够的智能来刷新视图和存储过程所需。
在迁移到x64平台之后,我们需要对我们的SQL数据库进行版本pipe理,而旧版本则随着迁移而中断。 我们编写了一个使用SQLDMO将所有SQL对象映射到一个文件夹的C#应用程序:
根 服务器名称 数据库名称 模式对象 数据库触发器* .ddltrigger.sql function ..function.sql 安全 angular色 应用程序angular色 .approle.sql 数据库angular色 .role.sql 架构* .schema.sql 用户 .user.sql 存储 全文目录* .fulltext.sql 存储过程 ..proc.sql 同义词* .synonym.sql 表 ..table.sql 约束 ... chkconst.sql ... defconst.sql 索引 ... index.sql 按键 ... fkey.sql ... pkey.sql ... ukey.sql 触发器 ... trigger.sql types 用户定义的数据types ..uddt.sql XML架构集合* ..xmlschema.sql 查看 ..view.sql 索引 ... index.sql 触发器 ... trigger.sql
然后,应用程序会将新写入的版本与存储在SVN中的版本进行比较,如果存在差异,则会更新SVN。 我们确定,一晚上运行一次这个过程就足够了,因为我们并没有对SQL做太多改变。 它使我们能够跟踪所有我们关心的对象的变化,并且允许我们在出现严重问题时重build我们的完整模式。
我前一段时间写了这个程序, http: //sqlschemasourcectrl.codeplex.com/,它会扫描你的MSFT SQL数据库的频繁,并自动转储您的对象(表,视图,特效,函数,sql设置)到SVN。 奇迹般有效。 我使用它与Unfuddle(这使我可以在登记提醒)
典型的解决scheme是根据需要转储数据库并备份这些文件。
根据您的开发平台,可能会有开源插件可用。 滚动你自己的代码来做到这一点通常是微不足道的。
注意:您可能需要备份数据库转储,而不是将其放入版本控制。 这些文件在版本控制中可能会变得非常快,并且会导致整个源代码pipe理系统变慢(我现在回想起CVS的一个恐怖故事)。
我们刚刚开始使用Team Foundation Server。 如果你的数据库是中等大小的,那么visual studio有一些很好的项目集成,比较内置比较,数据比较,数据库重构工具,数据库testing框架,甚至数据生成工具。
但是,该模型并不适合非常大的或第三方数据库(encryption对象)。 所以,我们所做的只是存储我们自定义的对象。 Visual Studio /团队基础服务器工作得很好。
TFS数据库主pipe。 博客
MS TFS网站
我同意ESV的答案,为了这个确切的原因,我开始了一个小项目,以帮助维护一个非常简单的文件中的数据库更新,然后可以保持长期的源代码。 它允许开发人员轻松更新,以及UAT和生产。 该工具可以在Sql Server和MySql上运行。
一些项目function:
- 允许模式更改
- 允许价值树人口
- 允许单独的testing数据插入例如。 UAT
- 允许select回滚(不自动)
- 保持对SQL Server和Mysql的支持
- 有能力导入您的现有数据库版本控制与一个简单的命令(只有SQL服务器…仍然工作在MySQL)
代码托pipe在谷歌代码上。 请查看Google代码以获取更多信息
前一段时间,我发现一个VB BAS模块,使用DMO和VSS对象来获取整个数据库脚本和VSS。 我把它变成一个VB脚本,并在这里发布。 你可以很容易地取出VSS调用,并使用DMO的东西来生成所有的脚本,然后从调用VBScript的同一batch file中调用SVN来检查它们?
戴夫J
我也在使用数据库扩展属性系列程序存储的数据库中使用一个版本。 我的应用程序有每个版本步骤的脚本(即从1.1到1.2)。 部署时,将查看当前版本,然后逐个运行脚本,直到达到最后一个应用程序版本。 没有直接的“最终”版本的脚本,即使部署在干净的数据库上,通过一系列升级步骤进行部署。
现在我想补充的是,我前两天在MS校园里看到了关于即将到来的VS DB版本的演示。 演示文稿是专门针对这个话题,我被炸出水面。 你一定要检查一下,新的工具集中在T-SQL脚本(CREATE)中保存模式定义,运行时增量引擎将部署模式与定义的模式进行比较,并执行delta ALTER和与源代码集成的集成,直到并包括MSBUILD持续集成自动构build下降。 该下拉菜单将包含一个新的文件types,即.dbschema文件,这些文件可以发送到部署站点,命令行工具可以执行实际的“deltas”并运行部署。 我有一个关于这个主题的博客条目,并且链接到VSDE下载,你应该检查它们: http ://rusanu.com/2009/05/15/version-control-and-your-database/
这是一个非常古老的问题,但是现在很多人都在试图解决这个问题。 他们所要做的就是研究Visual Studio数据库项目。 没有这个,任何数据库开发看起来都很虚弱。 从代码组织到部署到版本控制,它简化了一切。
根据我的经验,解决scheme是双重的:
-
您需要处理在开发过程中由多个开发人员完成的对开发数据库的更改。
-
您需要处理客户站点中的数据库升级。
为了处理#1,你需要一个强大的数据库差异/合并工具。 最好的工具应该能够尽可能地执行自动合并,同时允许您手动解决未处理的冲突。
完美的工具应该通过使用3-way合并algorithm来处理合并操作,该algorithm考虑到THEIRS数据库和MINE数据库中相对于BASE数据库所做的更改。
我写了一个商业工具,提供SQLite数据库的手动合并支持,我目前正在添加对SQLite的3路合并algorithm的支持。 查看http://www.sqlitecompare.com
为了处理#2,你将需要一个升级框架。
基本的想法是开发一个自动升级框架,知道如何从现有的SQL模式升级到新的SQL模式,并可以为每个现有的数据库安装构build升级path。
查看我在http://www.codeproject.com/KB/database/sqlite_upgrade.aspx的主题的文章,以获得我正在谈论的一般概念。;
祝你好运
Liron Levi
查看DBGhost http://www.innovartis.co.uk/ 。 我已经使用了2年的自动化方式,而且效果很好。 它允许我们的数据库构build像Java或C构build一样发生,数据库除外。 你知道我的意思。
我会build议使用比较工具来为您的数据库提供一个版本控制系统。 一个好的select是xSQL Schema Compare和xSQL Data Compare 。
现在,如果您的目标是在版本控制下只有数据库模式,那么您可以简单地使用xSQL Schema Compare来生成模式的xSQL快照,并在您的版本控制中添加这些文件。 相比之下,要还原或更新到特定版本,只需将数据库的当前版本与目标版本的快照进行比较。
唉,如果您想要在版本控制下也有数据,您可以使用xSQL Data Compare为您的数据库生成更改脚本,并在您的版本控制中添加.sql文件。 然后你可以执行这些脚本来恢复/更新你想要的任何版本。 请记住,对于“还原”function,您需要生成更改脚本,这些脚本在执行时将使版本3与版本2相同,而对于“更新”function,则需要生成相反的更改脚本。
最后,借助一些基本的批处理编程技巧,您可以通过使用命令行版本的xSQL Schema Compare和xSQL Data Compare来自动执行整个过程
免责声明:我隶属于xSQL。