我想让我的数据库处于版本控制之下。

我总是希望在那里至少有一些数据(如alumb提到的:用户类型和管理员)。我还经常需要大量生成的测试数据来进行性能度量。

如何对数据库应用版本控制?


当前回答

你没有提到任何关于目标环境或约束的细节,所以这可能并不完全适用……但如果您正在寻找一种有效跟踪不断变化的DB模式的方法,并且不反对使用Ruby, ActiveRecord的迁移正适合您。

迁移使用Ruby DSL以编程方式定义数据库转换;每个转换都可以应用或(通常)回滚,允许您在任何给定的时间点跳转到您的DB模式的不同版本。定义这些转换的文件可以像任何其他源代码一样检入版本控制。

因为迁移是ActiveRecord的一部分,它们通常在全栈Rails应用程序中使用;然而,你可以用最少的努力独立于Rails使用ActiveRecord。请参阅这里,了解在Rails之外使用AR迁移的更详细处理。

其他回答

我们不存储数据库模式,而是存储对数据库的更改。我们所做的是存储模式更改,以便为数据库的任何版本构建更改脚本,并将其应用于客户的数据库。我写了一个数据库实用程序,它与我们的主应用程序一起分发,它可以读取脚本,并知道需要应用哪些更新。它还具有足够的智能,可以根据需要刷新视图和存储过程。

为了更快地将数据转储到源代码控制系统,您可以使用sysobjects中的版本信息来查看自上次以来哪些对象发生了更改。

设置:在每个数据库中增量地创建一个表,以保存上次检查时的版本信息(第一次运行时为空)。如果要重新扫描整个数据结构,请清除此表。

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脚本,并将它们放入您选择的源代码控制中。

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

注意:如果在任何数据库中使用非标准排序规则,则需要将/* COLLATE */替换为数据库排序规则。即COLLATE Latin1_General_CI_AI

在Red Gate,我们提供了一个工具,SQL Source Control,它使用SQL Compare技术将数据库与TFS或SVN存储库链接起来。该工具集成到SSMS中,让您像往常一样工作,只是现在允许提交对象。

对于基于迁移的方法(更适合于自动化部署),我们提供了SQL Change Automation(以前称为ReadyRoll),它作为Visual Studio项目创建和管理一组增量脚本。

在SQL源代码控制中,可以指定静态数据表。它们作为INSERT语句存储在源代码控制中。

如果您正在讨论测试数据,我们建议您要么使用工具生成测试数据,要么通过您定义的部署后脚本生成测试数据,要么简单地将生产备份恢复到开发环境。

您还可以考虑迁移解决方案。它们允许您在c#代码中指定数据库模式,并使用MSBuild上下滚动数据库版本。

我目前正在使用DbUp,它工作得很好。

查看DBGhost http://www.innovartis.co.uk/。我已经在一个自动化的方式使用了2年,它工作得很好。它允许我们的DB构建非常像Java或C构建,除了数据库。你们能明白我的心情