做程序開發的人都知道版本控制的重要性, 代碼的管理好說,TFS/SVN/VSS/CVS,哪個都能用。但涉及到數據庫的版本控制,就不是太好做的。有的team是定期把數據庫的備份放到服務器上,但一來數據庫備份太大,而來二進制的備份文件沒有簡單的diff工具來比較變化。一個比較好的實踐是把數據庫的架構用腳本來表示。相關的討論可以Google之,前面幾篇文章,如 Coding Horror: Is Your Database Under Version Control?, 。遺憾的是中文沒能Google出什麼有意義的文章。
理論有了,下面就是實踐的問題。怎麼生成和管理腳本。SQLServer2005右鍵點擊數據庫,[任務]->[腳本生成]能生成一堆腳本,但我還不知道有誰能夠在不修改原始輸出的情況下一次性運行成功這些腳本。搜了一把,生成SQLServer數據庫腳本四法裡介紹了一個scptxfr.exe,遺憾的是我沒能在SQLServer2005裡找到這個工具。倒是在SQLServer Hosting Toolkit裡找到了一個Data Publishing Wizard能生成可用的數據庫創建腳本,這個工具支持GUI和命令行,用起來很是方便。遺憾的是生成的腳本裡只包含schema和下一級表、視圖、存儲過程等對象的名稱,而不包含數據庫名,害得我一運行,master數據庫裡多了一堆表。為了解決這個問題,我用Python寫了個腳本來生成創建數據庫和using數據庫的語句,再用了一個命令行封裝一下。
CreatNewdb.cmd:
以下為引用的內容:
sqlpubwiz script -schemaonly -d %1 -f %1.sql.tmp echo "publish done"
if exist %1.sql del %1.sql
echo "adding database creating statements"
Python createNewDB.py %*
del %1.sql.tmp
CreateNewDB.py
以下為引用的內容:
import sys
fmt = """
USE [master]
GO
/****** object: Database [%s] ******/
IF EXISTS (SELECT name FROM sys.databases WHERE name = N'%s')
DROP DATABASE [%s]
GO
CREATE DATABASE [%s]
GO
USE [%s]
"""
if len(sys.argv) != 2:
print("createNewDB <database name>")
sys.exit()
databaseName = sys.argv[1]
inFile = open(databaseName + ".sql.tmp", encoding="utf-16")
content = inFile.read()
inFile.close()
outFile = open(databaseName + ".sql", "w", encoding="utf-8")
outFile.write(fmt % (databaseName, databaseName, databaseName, databaseName, databaseName))
outFile.write(content)
現在基本解決了數據庫創建腳本的問題。但後續的修改如何跟蹤?
一是維護一個大的創建腳本。好處是只需要維護一個腳本,執行起來也比較方便。但跟蹤變化不是一件很容易的事情。
二是維持數據庫創建腳本的相對穩定,要修改一個數據庫對象時就為該對象創建一個腳本。好處是容易跟蹤變化,但腳本執行的順序不易維護,還需要再寫一個批處理命令來按一定書序調用這些sql腳本。
都是一些想法,還有待實踐檢驗。