[实战]如何对比两个数据库之间的变化

目录

  1. 前言
  2. 用于查询所有字段的sql语句
  3. 用于查询存储过程里是否包含某一关键字的sql语句
  4. 用于查询Schedule Job里的step是否包含某一关键字的sql语句
  5. 实现
    1. Step 1
    2. Step 2
    3. Step 3
  6. 礼物

前言

相信很多撸友都曾经接到过下面这样一个工作:

  1. 要求对比两个不同版本数据库之间的变化,并对统计该变化对已有系统的影响
  2. 并根据影响,请检索所有现行系统相关的存储过程,作出相应的修改。

或许最终的目的不一定是要统计什么,但前面的准备工作却是一样。也虽然我们确实可以用类似SQL Compare这样的商业软件搞定,但最终会发现被软件绑手绑脚,无法施展开想要的工作。那么就有了下面这么一小段学习的历程。
本文指针对小弟工作中遇到的问题展开,如果有不足之处欢迎补充。

用于查询所有字段的sql语句

SELECT
	obj.[name] AS TabName,
	col.colorder AS ColOrder,
	col.[name] AS ColName,
	COLUMNPROPERTY( col.id,col.name, 'IsIdentity' ) AS ColIsIdentity,
	(CASE 
		WHEN (SELECT count(*) FROM sysobjects WHERE ([name] in
			(SELECT name FROM sysindexes WHERE (id=col.id) AND (indid in 
				(SELECT indid FROM sysindexkeys WHERE (id=col.id) AND (colid in 
					(SELECT colid FROM syscolumns WHERE (id=col.id) AND ([name]=col.[name]))
			))))) AND xtype = 'PK') > 0 THEN 1
		ELSE 0
	END) AS ColIsPK,
	t.[name] AS ColType,
	col.[length] AS ColLen,
	COLUMNPROPERTY(col.id,col.name,'PRECISION' ) AS ColPrecosion,
	ISNULL(COLUMNPROPERTY(col.id, col.name, 'Scale' ),0) AS ColScale,
	col.isnullable AS IsNullable,
	ISNULL(com.text,'') AS ColDefaultValue,
	ISNULL(ext.[value],'' ) AS ColDiscription
-- INTO {the database as you like}
FROM syscolumns col
INNER JOIN sysobjects obj ON col.id=obj.id AND obj.xtype='U' AND obj.[name]<>'dtproperties'
LEFT JOIN systypes t ON col.xtype=t.xusertype
LEFT JOIN syscomments com ON col.cdefault=com.id
LEFT JOIN sys.extended_properties ext ON col.id=ext.major_id AND col.colid=ext.minor_id
ORDER BY TabName,ColOrder

用于查询存储过程里是否包含某一关键字的sql语句

select B.name AS OBJECT_NAME,   B.TYPE
from sys.all_sql_modules a inner join sys.all_objects b on a.object_id = b.object_id and b.type IN('P', 'F')
where charindex( lower('KEY_WORD'), lower(definition) ) > 0 --and charindex( lower('retrieve'), lower(definition) ) = 0
ORDER BY 1 

用于查询Schedule Job里的step是否包含某一关键字的sql语句

select j.name, js.step_name
from msdb..sysjobs  j inner join msdb..sysjobsteps js on j.job_id = js.job_id
where j.enabled =1
and charindex('KEY_WORD', js.command) >0

友情提示

本文重点全在上面三段脚本,已经看明白了的那么就请笑一笑忽略下文吧:) 微喷,微喷。

具体实现

有了上面这个基础代码,那么我们就能来搞搞阵了。

Step-1

思路是这样的,既然我们能查询到两个数据库的结构(利用上面这个代码),那么就能利用查询出来的列表来做一下比较了;又由于我们用到的这个第三方库大概有12k+的字段,所以我先把查询出来的列表分别存到两个表PROD1812UAT41812里面(单表双表请随意,单表多个字段标识下库名)。

命名上我分别加了p_u_开头,个人喜好吧。下面这个工具叫SQL Complete(Lite),一个很小的免费工具,虽然ssms有提供类似功能,但提示效果总感觉不如这个快捷。当然,还有其他更好以及收费工具。

还有就是上面有些信息我自己认为是没必要作为比较的,所以拿掉了。

Step-2

还是先贴代码

SELECT * FROM Prod1812 p
FULL OUTER JOIN UAT41812 u ON p.p_TabName=u.u_TabName AND p.p_ColName=u.u_ColName
WHERE
	p.p_ColName IS NULL OR --左边p是空的时候,表示右边u的是新的字段或者重命名过的字段
	u.u_ColName IS NULL OR --右边u是空的时候,表示左边p的字段被删除了或者被重命名了
	p.p_ColType<>u.u_ColType OR --类型被修改了
	p.p_ColLen<>u.u_ColLen OR --长度被修改了
	p.p_ColScale<>u.u_ColScale --小数点长度(精度)被修改了

这里说的是什么呢?
首先注意下这里的FULL OUTER JOIN,请暴力地理解为当使用p.p_TabName=u.u_TabName AND p.p_ColName=u.u_ColName这个条件地时候,左边是NULL也要,右边是NULL也要的意思。这里也不需要用到CROSS JOIN
然后是WHERE里面地条件,可以根据实际情况筛选(还有默认值啊之类的)。
由于我们的系统只是查询这个第三方的数据库,所以本次只需要检查跟SELECT相关的就可以了,类似默认值之类的不在检查列表之内。

我把上面跑出来的结果继续存进一个表Change1812里,对,空间不用钱,但数据库很累,所以跑一次就记下来。

Step-3

写邮件吹牛逼汇报进度。
对得到的数据放进Excel稍加格式上的处理之后就能出到下面这个效果了,各位技术员朋友们,做到这里赶紧写一封邮件跟老板们汇报下进度吧,不然要吃大亏啦,别问我怎么知道的。搞技术的时候总喜欢埋头苦干,直到出最后结果的时候才汇报,其实那个时候已经太晚了。这次第三方库升级,检查到这一步的时候,发现一共有700+个修改,往大了说,很有可能使毁灭性的升级,往小了说,也有可能压根就没用到几个,毕竟12k+的字段,700+也就是6%不到,何况还可能有重复的。一定要吧把这些count出来的数字列出来,详细的数据只是作为辅助证明自己不只是简单的吹牛逼而已。切记切记。

Step-4

继续埋头苦干,这里要用到前面的第二段sql语句了。
目的是为了检索出本地库究竟有多少用到Change1812表里那些那些已经标记被修改了了的字段,得出结果后存进Impact181表里,如果本地库大的话这里其实要跑很久的,简易在Staging里跑,不要在Prod里跑。就不贴详细代码了,核心都在那里了。

礼物

嗯,其实第三段sql语句是没用到的,当成礼物送给愿意看到最后面的朋友们。:P

posted @ 2019-01-03 22:41  黄铨  阅读(2578)  评论(1编辑  收藏  举报