[實戰]如何對比兩個資料庫之間的變化
目錄
前言
相信很多擼友都曾經接到過下面這樣一個工作:
- 要求對比兩個不同版本資料庫之間的變化,並對統計該變化對已有系統的影響。
- 並根據影響,請檢索所有現行系統相關的儲存過程,作出相應的修改。
或許最終的目的不一定是要統計什麼,但前面的準備工作卻是一樣。也雖然我們確實可以用類似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+
的欄位,所以我先把查詢出來的列表分別存到兩個表PROD1812
跟UAT41812
裡面(單表雙表請隨意,單表多個欄位標識下庫名)。
命名上我分別加了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