我想让我的数据库处于版本控制之下。
我总是希望在那里至少有一些数据(如alumb提到的:用户类型和管理员)。我还经常需要大量生成的测试数据来进行性能度量。
如何对数据库应用版本控制?
我想让我的数据库处于版本控制之下。
我总是希望在那里至少有一些数据(如alumb提到的:用户类型和管理员)。我还经常需要大量生成的测试数据来进行性能度量。
如何对数据库应用版本控制?
当前回答
为了更快地将数据转储到源代码控制系统,您可以使用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
其他回答
因为我们的应用程序必须跨多个rdbms工作,所以我们使用与数据库无关的Torque格式(XML)将模式定义存储在版本控制中。我们还以以下XML格式对数据库的引用数据进行版本控制(其中“关系”是其中一个引用表):
<Relationship RelationshipID="1" InternalName="Manager"/>
<Relationship RelationshipID="2" InternalName="Delegate"/>
etc.
然后,我们使用自己开发的工具来生成从数据库版本X到版本X + 1所需的模式升级和引用数据升级脚本。
为了更快地将数据转储到源代码控制系统,您可以使用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
根据我的经验,解决方法有两个:
您需要处理开发数据库的更改,这些更改是由多个开发人员在开发期间完成的。 需要处理客户站点的数据库升级。
为了处理#1,你需要一个强大的数据库差异/合并工具。最好的工具应该能够尽可能地执行自动合并,同时允许您手动解决未处理的冲突。
完美的工具应该通过使用3-way合并算法来处理合并操作,该算法考虑到相对于BASE数据库在their数据库和MINE数据库中所做的更改。
我写了一个商业工具,为SQLite数据库提供手动合并支持,我目前正在为SQLite添加3路合并算法的支持。请登录http://www.sqlitecompare.com查看
为了处理第2点,你需要一个升级框架。
基本思想是开发一个自动升级框架,该框架知道如何从现有的SQL模式升级到更新的SQL模式,并且可以为每个现有的DB安装构建一个升级路径。
在http://www.codeproject.com/KB/database/sqlite_upgrade.aspx上查看我关于这个主题的文章,了解我所说的内容。
祝你好运
利龙·列维
你可能想看看Liquibase (http://www.liquibase.org/)。即使您不使用该工具本身,它也能很好地处理数据库变更管理或重构的概念。
在VS 2010中,使用数据库项目。
脚本化数据库 对脚本或直接进行更改 您的db服务器 使用数据>同步 模式比较
使一个完美的DB版本解决方案,并使同步DB的微风。