SQL Compare是一款比較和同步SQL Server數據庫結構的工具。現有超過150,000的數據庫管理員、開發人員和測試人員在使用它。當測試本地數據庫,暫存或激活遠程服務器的數據庫時,SQL Compare將分配數據庫的過程自動化。html
咱們的團隊爲商業組織開發實際應用程序;主要是格魯吉亞銀行。這些應用程序基於MS SQL Server做爲數據庫的.Net-Windows-Forms應用程序。它們具備許多業務邏輯,這些邏輯包含在數據庫例程中,例如存儲過程、函數、視圖和SQL CLR。sql
絕不奇怪,考慮到客戶業務的性質,咱們沒有訪問客戶數據庫或數據進行開發、測試或部署的權限。在TFS源代碼管理下,咱們只有開發數據庫及其人工測試數據。開發人員在本身的數據庫副本上工做,每一個副本都有本身的示例數據,而且他們使用Redgate SQL Source Control提交開發更改。而後,咱們使用SQL Compare命令行來自動化數據庫部署。在本文中,我將解釋如何實現此目標,並舉例說明如何比較相同或不一樣分支中的數據庫的兩個修訂版,並生成部署腳本。數據庫
在源代碼管理中管理數據庫服務器
咱們的數據庫源代碼控制和分支策略很簡單。咱們在Trunk中擁有最新的代碼庫;整個應用程序都在那裏,包括其中的數據庫部分。全部新功能和錯誤修復最初都在Trunk中進行。咱們建立的每一個分支只是Trunk的一個副本,所以表明了代碼庫的完整時間點狀態。在應用了一些更改並簽入Trunk以後,咱們能夠根據須要將其合併到這些分支中的任何一個。一般,這是爲了修復已報告的錯誤,但當對咱們的客戶來講很重要時,咱們還須要可以合併小的功能更改。例如,並不是每一個客戶都能負擔得起部署每一個版本的費用,所以他們部署的版本一般落後三個或四個版本。可是,他們仍然須要咱們爲當前版本部署緊急修復程序,偶爾會使用一些「專有」功能。架構
那麼,當咱們開發軟件時,這一切如何工做?讓咱們將其稱爲「under-source-control-application」(簡稱USCAPP)。咱們在USCAPP_Trunk中擁有最新的代碼庫,並在TFS分支下提供了一些發行版本,稱爲v241、v242等。app
直接或經過合併進行的全部更改均可以經過Trunk及其分支的普通TFS檢入完成。在每次簽入時,TFS都會建立一個稱爲變動集的東西,它具備惟一的參考號。變動集表示源代碼管理中整個代碼庫的快照。像任何其餘源代碼控制系統同樣,TFS能夠針對任何給定的變動集編號,爲任何修訂生成代碼庫的時間點狀態。ide
固然,對於集合中的全部TFS項目(包括其分支機構),TFS變動集編號都是全局的,而且每次對該項目集合進行每次檢入時,TFS變動集編號都將逐漸增長。對咱們來講,這意味着USCAPP_Trunk及其全部分支v24一、v242等都共享相同的、全球的、不斷增加的變動集號。函數
開發人員進行更改,每一個人都在本身的專用數據庫上工做,並經過SQL Source Control簽入更改,這些更改將更新USCAPP_Trunk中的代碼。根據須要,咱們將所需的變動集合併到其餘分支,在這些分支中建立新的變動集。所以,假設最新版本爲v245,而且咱們知道客戶A已將v242部署到生產環境中。該客戶尚不能升級到最新版本,但已部署了一個附加的升級腳本以修復一些錯誤並進行一些小的改進。換句話說,客戶A正在運行很是特定的v242版本,咱們能夠將其轉換爲TFS變動集編號,該編號惟一地標識其已部署的分支v242的代碼庫的時間點狀態。工具
使用SQL Compare命令行自動生成更改腳本測試
咱們的目標是使生成同步SQL腳本的過程自動化,該腳本覆蓋自上次發佈腳本以來發生的全部更改。
假設客戶A已經部署了分支v242,而且該數據庫的發行版本標記有人類可讀的版本號2.4.2.0,該版本號對應於變動集編號87300,即它是在變動集87300是當前最新版本時發佈的代碼庫的全局變動集編號。
此後一個月過去了,咱們已經在數據庫中進行了更改,如今TFS中當前的更改集數量爲88100。如今,咱們要生成一個腳本,其中包含當月所作的每一個更改,所以將數據庫的v2.4.2.0升級到變動集編號88100表示的狀態,咱們將其稱爲v2.4.2.1。
爲此,咱們須要從TFS中檢索數據庫的兩個時間點狀態,一個表明源數據庫(不會改變),另外一個表明目標數據庫(咱們要升級)。所以,對於客戶A,變動集88100表明源,而87300表明目標。咱們須要比較這兩種狀態以找出差別,而後生成一個腳本以同步目標,以便其狀態與源相同。對於兩個數據庫中都存在但有差別的任何數據庫對象,必須更改目標中對象的定義以匹配其在源中的定義。應該建立源中存在但目標中不存在的任何對象,應該刪除目標中存在但源中不存在的任何對象。
好消息是,咱們沒必要手動執行此操做。SQL Compare GUI和SQL Compare命令行均支持此功能。咱們但願使該過程自動化,所以咱們使用命令行並將適當的參數傳遞給該命令行以生成同步腳本。咱們還須要仔細記錄該腳本將數據庫的2.4.2.0版本升級到v2.4.2.1。固然,這裏咱們也須要一些保護措施。其中一項是檢查,該檢查將中止在不是v2.4.2.0的任何數據庫上運行此腳本。在這裏,我不會進行演示,可是最後,我將更詳細地討論這些需求。
比較同一分支中的兩個修訂
首先,我將描述咱們如何發佈稱爲「修復」的腳本,該腳本主要用於部署一些錯誤修復和較小的改進。主要版本保持不變。
咱們使用SQL Compare命令行進行此操做,傳遞一個XML參數文件(argfile),該文件包含指示SQL Compare如何執行比較的全部必需命令行開關的值。或者,您能夠指定每個到命令行的開關,或在PowerShell中「splat」參數。
在這種狀況下,惟一須要傳遞給SQL Compare的參數是XML Argfile的合格文件名,稱爲「shared.xml」
「%programfiles(x86)%\ Red Gate \ SQL Compare 13 \ sqlcompare」 /Argfile:"shared.xml「
argfile的內容應徹底按照SQL Compare命令行的在線文檔中的說明填寫。這是真實的示例:
<commandline> <SourceControl1 /> <Revision1>88100</Revision1> <SourceControl2 /> <Revision2>87300</Revision2> <Options>NoDeploymentLogging,IgnoretSQLt,IgnoreFillFactor,IgnoreWhiteSpace,IgnoreFileGroups,IgnoreUserProperties,IgnoreWithElementOrder,IgnoreDatabaseAndServerName,CaseSensitiveObjectDefinition,ObjectExistenceChecks,DropAndCreateInsteadofAlter,ForceColumnOrder,DoNotOutputCommentHeader,IgnoreUsersPermissionsAndRoleMemberships</Options> <ScriptsFolderXML>Command Line\SourceControlAddress v242.xml</ScriptsFolderXML> <Filter>Command Line\Filters\Shared.scpf</Filter> <ReportType>Interactive</ReportType> <Report>Command Line\Output\Shared.html</Report> <ScriptFile>Command Line\Output\Shared.sql</ScriptFile> <Force /> <Verbose /> </commandline>
Argfile包含五個命令行開關,咱們使用它們來定義所需的行爲。/ Sourcecontrol1和/ Sourcecontrol2切換指定咱們的源,和目標,是源控制腳本的一個文件夾,在這種狀況下,版本分別爲88100和87300。
<SourceControl1 /> <Revision1>88100</Revision1> <SourceControl2 /> <Revision2>87300</Revision2>
所述<ScriptsFolderXML>開關包含完整的文件路徑爲XML文件,SourceControlAddress v242.xml。該文件以下所示,包含分支v242的數據庫的源代碼控制地址:
<?xml version="1.0" encoding="utf-16" standalone="yes"?> <ISOCCompareLocation version="1" type="TfsLocation"> <ServerUrl>http://tfs:8080/tfs/projects</ServerUrl> <SourceControlFolder>$/USCAPP/Branches/v242/Database/Schema</SourceControlFolder> </ISOCCompareLocation>
這是SQL Compare應從中恢復87300和88100變動集的地址。當執行SQL Compare的命令行版本時,它將把這些變動集還原爲「腳本文件夾」(在撰寫本文時,還原到Windows Temp中的文件夾中),並使用88100做爲源和87300做爲目標進行比較,以生成最終的升級腳本。
比較兩個不一樣分支中的數據庫
咱們用來發布已經在Trunk中完成的全部新功能的過程與錯誤修正版本稍有不一樣,可是主要概念保持不變。一樣在這種狀況下,咱們必須比較數據庫架構的兩個不一樣狀態。即便它們的「真理來源」做爲TFS源代碼管理中的版本存在,它們也被導出到文件夾,做爲Redgate稱爲「腳本文件夾」的東西。而後能夠將它們做爲兩個數據庫模式進行比較。在這種狀況下,不一樣之處在於咱們不是在一個TFS分支中比較由變動集表示的兩個修訂版(或時間點狀態),而是在如今表示版本的兩個分支之間進行比較。
要逐步進行:該過程首先從Trunk分支中建立一個新分支,併爲其指定一個適當的名稱。例如,若是v2.4.2是USCAPP應用程序的最後發行版本,那麼在發行該版本時,咱們已經建立了一個名爲v242的分支。如今,咱們已經對Trunk進行了更多更改,從邏輯上講,咱們將發佈v2.4.3版本,所以咱們的新分支將稱爲v243,從那時開始,就其所包含的內容而言,它將做爲Trunk分支的確切副本。
如今,咱們應該比較兩個單獨分支的兩個變動集。咱們用於比較的變動集必須是剛剛建立的新v243分支的變動集,而且是客戶A已應用的上一個分支v242的最新發布的部署腳本所對應的變動集。此比較將揭示僅在Trunk的數據庫上發生的更改,而上一個分支v242的數據庫中缺乏這些更改。
爲此,咱們須要指定一個而不是兩個源代碼管理文件夾位置,一個用於包含源/ ScriptsFolderXML1的TFS分支,另外一個用於包含目標/ ScriptsFolderXML2的分支。咱們使用SQL Compare保留關鍵字「HEAD」來指定咱們想要源分支的最新的源控件更改集。生成的Argfile以下所示:
<commandline> <SourceControl1 /> <Revision1>HEAD</Revision1> <SourceControl2 /> <Revision2>88100</Revision2> <Options>NoDeploymentLogging,IgnoretSQLt,IgnoreFillFactor,IgnoreWhiteSpace,IgnoreFileGroups,IgnoreUserProperties,IgnoreWithElementOrder,IgnoreDatabaseAndServerName,CaseSensitiveObjectDefinition,ObjectExistenceChecks,DropAndCreateInsteadofAlter,ForceColumnOrder,DoNotOutputCommentHeader,IgnoreUsersPermissionsAndRoleMemberships</Options> <ScriptsFolderXML1>Command Line\SourceControlAddress v243.xml</ScriptsFolderXML1> <ScriptsFolderXML2>Command Line\SourceControlAddress v242.xml</ScriptsFolderXML2> <Filter>Command Line\Filters\Shared.scpf</Filter> <ReportType>Interactive</ReportType> <Report>Command Line\Output\Shared.html</Report> <ScriptFile>Command Line\Output\Shared.sql</ScriptFile> <Force /> <Verbose /> </commandline>
這是目標的源代碼管理腳本位置XML文件(SourceControlAddress v242.xml):
<?xml version="1.0" encoding="utf-16" standalone="yes"?> <ISOCCompareLocation version="1" type="TfsLocation"> <ServerUrl>http://tfs:8080/tfs/projects</ServerUrl> <SourceControlFolder>$/USCAPP/Branches/v242/Database/Schema</SourceControlFolder> </ISOCCompareLocation>
這是源代碼之一(SourceControlAddress v243.xml):
<?xml version="1.0" encoding="utf-16" standalone="yes"?> <ISOCCompareLocation version="1" type="TfsLocation"> <ServerUrl>http://tfs:8080/tfs/projects</ServerUrl> <SourceControlFolder>$/USCAPP/Branches/v243/Database/Schema</SourceControlFolder> </ISOCCompareLocation>
再一次,咱們僅使用Argfile的地址做爲惟一參數來調用SQL Compare命令行:
「%programfiles(x86)%\ Red Gate \ SQL Compare 13 \ sqlcompare」 /Argfile:"shared.xml「
在SQL Compare命令行完成其工做以後,在「Shared.sql」 文件中,咱們有了能夠在目標數據庫上運行的升級腳本,以將其升級到最新的主要版本。
進一步要求
在現實生活中,咱們始終須要仔細檢查自動生成的腳本,添加檢查和控件,以確保例如以正確的順序將全部必需的升級腳本應用到預期的數據庫版本。咱們還須要對SQL Compare的自動生成的部署腳本進行少許添加和自定義,例如處理數據插入或向每一個腳本添加標頭信息(建立腳本時,版權信息,聯繫信息等)。 或在每一個自動生成的腳本的末尾附加一些動態生成的SQL腳本,以識別客戶。
經過使用自定義遷移腳本修改SQL Compare部署,能夠實現不少這樣的目標,儘管實際上咱們遇到了一些困難,例如它們減慢了SQL Source Control的運行速度或部署前和部署後腳本。
對咱們來講,另外一個須要考慮的因素是,SQL Compare遷移和部署前或部署後腳本是靜態的,而咱們的要求是動態生成的腳本。相反,咱們在Visual Studio中構建了一個簡單,輕便的工具,容許開發人員對SQL Compare腳本進行小的動態添加和自定義。
我避免在這裏進行深刻研究的另外一個複雜性是,對於咱們的每一個客戶,咱們的源代碼管理幹線將客戶數據庫的全部共享邏輯與包含該組織專有的定製代碼的小型例程結合在一塊兒。在本文中,我演示瞭如何使用SQL Compare命令行來部署全部客戶通用的數據庫結構和代碼。儘管該過程與特定於客戶的例程基本相同,可是須要進行一些小的調整,以確保始終將獨有功能僅部署到該客戶的生產數據庫中,而且沒有任何客戶能夠看到專門爲另外一位客戶編寫的邏輯。我將在下一篇文章中描述咱們如何實現這一目標!
結論
咱們的經驗是Redgate Source Control和SQL Compare能夠協同工做,而且對咱們自動化腳本生成過程起到了很大的做用。SQL Compare容許對其從Git或TFS源代碼控制中提取腳本的方式進行很是精細的控制,從而爲咱們節省了大量手動腳本編寫。咱們將看到可以自動生成相應的回滾(降級)腳本以及升級腳本的更多可能性。它只須要反轉咱們用於源和目標的變動集並啓動SQL Compare命令行便可!它是一種多功能工具。
本教程內容到這裏就結束了,但願對您有所幫助~