1. 程式人生 > >[實戰]如何對比兩個資料庫之間的變化

[實戰]如何對比兩個資料庫之間的變化

目錄

  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