逐步解說:比較資料庫與資料庫專案的結構描述
這個主題適用於:
Visual Studio Ultimate |
Visual Studio Premium |
Visual Studio Professional |
Visual Studio Express |
---|---|---|---|
在此逐步解說中,您會使用 Visual Studio 來比較「資料庫專案」(Database Project) 的「結構描述」(Schema) 與資料庫的結構描述。在考量您的小組使用資料庫專案與資料庫的方式下,您可能會想要複製其中一方的結構描述變更。 當小組在進行資料庫開發週期時,您可能會遇到下列典型案例:
以專案為來源而資料庫為目標。您可以使用資料庫專案來開發或維護資料庫。 在您變更專案的結構描述之後,您會將這些變更複製到裝載於開發用伺服器上的資料庫。 之後,您的小組可以將此資料庫部署至實際執行伺服器。
您在此逐步解說中執行的比較會從結構描述差異產生資料定義語言 (DDL) 指令碼。 然後您可以使用此指令碼,將資料庫專案的全部或部分套用到此資料庫。 如需詳細資訊,請參閱將專案中的變更傳送到資料庫。
以資料庫為來源而專案為目標。可能會在實際執行資料庫的結構描述中找到錯誤,或是該結構描述可能過期且需要更新。 這項探索可能會要求小組將緊急的更新套用到資料庫。 為了讓專案與資料庫保持同步,您可以接著將更新匯入到資料庫專案中。 如需詳細資訊,請參閱 HOW TO:將資料庫的更新匯入到資料庫專案。
這個逐步解說將說明下列工作:
設定階段
建立資料庫專案。 新的專案一開始是空的。
從指令碼匯入資料庫結構描述。
設定、建置及部署資料庫專案到資料庫伺服器。 資料庫與專案具有相同的結構描述。
實際執行階段
將資料表加入到資料庫專案。 您會新增名為 InternationalShippers 的資料表,此資料表有三個資料行。
比較這兩個結構描述。 在這項比較中,您會將資料庫專案指定為來源,並將資料庫指定為目標。 因此,結果會將 InternationalShippers 資料表顯示為資料庫專案中的新資料表。
將專案中的變更傳送到資料庫。 您可以將資料庫專案中的新 InternationalShippers 資料表傳播至已部署的資料庫。 您若遵循此程序,便會覆寫部分的範例資料庫。
注意事項 您也可以將資料庫中的變更傳播至資料庫專案。 如需詳細資訊,請參閱 HOW TO:將資料庫的更新匯入到資料庫專案。
必要條件
您需要下列應用程式和權限,才能完成此逐步解說:
SQL Server 2008
在目標資料庫伺服器上建立和更新資料庫的權限
Visual Studio Premium 或 Visual Studio Ultimate
設定階段
建立資料庫專案
若要建立資料庫專案
在 [檔案] 功能表上,指向 [新增],然後按一下 [專案]。
[新增專案] 對話方塊隨即開啟。
展開 [已安裝的範本] 底下的 [資料庫] 節點,然後按一下 [SQL Server]。
在範本清單中,按一下 [SQL Server 2008 資料庫專案]。
在 [名稱] 中輸入 CompareProject,然後按一下 [確定]。
空的 CompareProject 專案會隨即開啟並出現在 [方案總管] 中。
從指令碼匯入資料庫結構描述
若要建立您可以從中匯入結構描述的指令碼
在 [檔案] 功能表上指向 [新增],然後按一下 [檔案]。
[新增檔案] 對話方塊隨即開啟。
按一下 [分類] 清單中的 [一般] (若尚未反白顯示)。
在 [範本] 清單中,按一下 [Sql 檔],然後再按一下 [開啟]。
Transact-SQL 編輯器隨即開啟。
複製下列程式碼,並將其貼入 Transact-SQL 編輯器中。
PRINT N'Creating Sales...'; GO CREATE SCHEMA [Sales] AUTHORIZATION [dbo]; GO PRINT N'Creating Sales.Customer...'; GO CREATE TABLE [Sales].[Customer] ( [CustomerID] INT IDENTITY (1, 1) NOT NULL, [CustomerName] NVARCHAR (40) NOT NULL, [YTDOrders] INT NOT NULL, [YTDSales] INT NOT NULL ); GO PRINT N'Creating Sales.Orders...'; GO CREATE TABLE [Sales].[Orders] ( [CustomerID] INT NOT NULL, [OrderID] INT IDENTITY (1, 1) NOT NULL, [OrderDate] DATETIME NOT NULL, [FilledDate] DATETIME NULL, [Status] CHAR (1) NOT NULL, [Amount] INT NOT NULL ); GO PRINT N'Creating Sales.Def_Customer_YTDOrders...'; GO ALTER TABLE [Sales].[Customer] ADD CONSTRAINT [Def_Customer_YTDOrders] DEFAULT 0 FOR [YTDOrders]; GO PRINT N'Creating Sales.Def_Customer_YTDSales...'; GO ALTER TABLE [Sales].[Customer] ADD CONSTRAINT [Def_Customer_YTDSales] DEFAULT 0 FOR [YTDSales]; GO PRINT N'Creating Sales.Def_Orders_OrderDate...'; GO ALTER TABLE [Sales].[Orders] ADD CONSTRAINT [Def_Orders_OrderDate] DEFAULT GetDate() FOR [OrderDate]; GO PRINT N'Creating Sales.Def_Orders_Status...'; GO ALTER TABLE [Sales].[Orders] ADD CONSTRAINT [Def_Orders_Status] DEFAULT 'O' FOR [Status]; GO PRINT N'Creating Sales.PK_Customer_CustID...'; GO ALTER TABLE [Sales].[Customer] ADD CONSTRAINT [PK_Customer_CustID] PRIMARY KEY CLUSTERED ([CustomerID] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF); GO PRINT N'Creating Sales.PK_Orders_OrderID...'; GO ALTER TABLE [Sales].[Orders] ADD CONSTRAINT [PK_Orders_OrderID] PRIMARY KEY CLUSTERED ([OrderID] ASC) WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF); GO PRINT N'Creating Sales.FK_Orders_Customer_CustID...'; GO ALTER TABLE [Sales].[Orders] ADD CONSTRAINT [FK_Orders_Customer_CustID] FOREIGN KEY ([CustomerID]) REFERENCES [Sales].[Customer] ([CustomerID]) ON DELETE NO ACTION ON UPDATE NO ACTION; GO PRINT N'Creating Sales.CK_Orders_FilledDate...'; GO ALTER TABLE [Sales].[Orders] ADD CONSTRAINT [CK_Orders_FilledDate] CHECK ((FilledDate >= OrderDate) AND (FilledDate < '01/01/2010')); GO PRINT N'Creating Sales.CK_Orders_OrderDate...'; GO ALTER TABLE [Sales].[Orders] ADD CONSTRAINT [CK_Orders_OrderDate] CHECK ((OrderDate > '01/01/2005') and (OrderDate < '01/01/2020')); GO PRINT N'Creating Sales.uspCancelOrder...'; GO CREATE PROCEDURE [Sales].[uspCancelOrder] @OrderID INT AS BEGIN DECLARE @Delta INT, @CustomerID INT BEGIN TRANSACTION SELECT @Delta = [Amount], @CustomerID = [CustomerID] FROM [Sales].[Orders] WHERE [OrderID] = @OrderID; UPDATE [Sales].[Orders] SET [Status] = 'X' WHERE [OrderID] = @OrderID; UPDATE [Sales].[Customer] SET YTDOrders = YTDOrders - @Delta WHERE [CustomerID] = @CustomerID COMMIT TRANSACTION END GO PRINT N'Creating Sales.uspFillOrder...'; GO CREATE PROCEDURE [Sales].[uspFillOrder] @OrderID INT, @FilledDate DATETIME AS BEGIN DECLARE @Delta INT, @CustomerID INT BEGIN TRANSACTION SELECT @Delta = [Amount], @CustomerID = [CustomerID] FROM [Sales].[Orders] WHERE [OrderID] = @OrderID; UPDATE [Sales].[Orders] SET [Status] = 'F', [FilledDate] = @FilledDate WHERE [OrderID] = @OrderID; UPDATE [Sales].[Customer] SET YTDSales = YTDSales - @Delta WHERE [CustomerID] = @CustomerID COMMIT TRANSACTION END GO PRINT N'Creating Sales.uspNewCustomer...'; GO CREATE PROCEDURE [Sales].[uspNewCustomer] @CustomerName NVARCHAR (40) AS BEGIN INSERT INTO [Sales].[Customer] (CustomerName) VALUES (@CustomerName); SELECT SCOPE_IDENTITY() END GO PRINT N'Creating Sales.uspPlaceNewOrder...'; GO CREATE PROCEDURE [Sales].[uspPlaceNewOrder] @CustomerID INT, @Amount INT, @OrderDate DATETIME, @Status CHAR (1)='O' AS BEGIN DECLARE @RC INT BEGIN TRANSACTION INSERT INTO [Sales].[Orders] (CustomerID, OrderDate, FilledDate, Status, Amount) VALUES (@CustomerID, @OrderDate, NULL, @Status, @Amount) SELECT @RC = SCOPE_IDENTITY(); UPDATE [Sales].[Customer] SET YTDOrders = YTDOrders + @Amount WHERE [CustomerID] = @CustomerID COMMIT TRANSACTION RETURN @RC END GO
按一下 [檔案] 功能表上的 [另存 SqlQuery_1.sql]。
[另存新檔] 對話方塊隨即開啟。
在 [物件名稱] 中,輸入 SampleImportScript.sql。
您可以將此檔案儲存至電腦上的任何位置。 請記下這個位置,因為您必須用於下一個程序中。
按一下 [儲存]。
在 [檔案] 功能表上,按一下 [關閉方案]。
接著,您要建立資料庫專案,並從您已建立的指令碼匯入結構描述。
若要從指令碼匯入資料庫結構描述
按一下 [專案] 功能表上的 [匯入資料庫指令碼]。
閱讀完 [歡迎] 頁面之後,請按 [下一步]。
按一下 [瀏覽],並瀏覽至您儲存 SampleImportScript.sql 檔案的位置。
按兩下 SampleImportScript.sql 檔案,然後按一下 [完成]。
如此就會匯入指令碼,而且該指令碼中定義的物件會加入至資料庫專案。
檢閱摘要,然後按一下 [完成]。
設定、建置和部署資料庫專案
這些程序會在「隔離的開發環境」(Isolated Development Environment) (或沙箱) 中建立有已匯入結構描述的資料庫,以便您開發和測試資料庫。
若要設定並建置資料庫專案
在 [方案總管] 中,按一下 CompareProject 專案。
按一下 [專案] 功能表上的 [CompareProject 屬性]。
CompareProject 專案的屬性隨即出現。
按一下 [部署] 索引標籤。
在 [部署動作] 清單中,按一下 [建立部署指令碼 (.sql) 並部署到資料庫]。
在 [目標資料庫設定] 中,按一下 [編輯]。
在 [連接屬性] 對話方塊中,針對您要使用的資料庫設定其連接屬性,然後按一下 [確定]。
[目標連接] 方塊會顯示正確的連接字串。
警告
您應該在測試伺服器、程式開發伺服器或本機電腦上建立資料庫。 您不應該使用實際執行伺服器。
在 [目標資料庫名稱] 方塊中輸入 CompareProjectDB。
在 [檔案] 功能表上按一下 [全部儲存]。
在 [建置] 功能表上,按一下 [建置方案]。
部署指令碼是根據您剛設定的專案屬性而建置。 建置的狀態會出現在 [輸出] 視窗中,而且 [組建: 1 成功或最新狀態] 會出現在最後一行。
若要部署資料庫專案
在 [方案總管] 中,按一下 CompareProject 專案。
按一下 [建置] 功能表上的 [部署 CompareProject]。
此外,您也可以用滑鼠右鍵按一下 [方案總管] 中的專案,然後按一下 [部署]。
警告
您應該針對測試伺服器、程式開發伺服器或本機電腦執行這項部署, 您不應該使用實際執行伺服器。
資料庫專案即會部署到新的資料庫。 部署的狀態會出現在 [輸出] 視窗中,而且 [部署成功] 會出現在最後一行。
實際執行階段
將資料表加入到資料庫專案
若要將資料表加入至專案
按一下 [檢視] 功能表上的 [資料庫結構描述檢視]。
[結構描述檢視] 隨即開啟,並顯示 CompareProject 專案的結構描述。
在 [結構描述檢視] 中,展開 CompareProject 節點,然後展開 [結構描述] 節點。
以滑鼠右鍵按一下 [Sales],然後指向 [加入],再按一下 [資料表]。
[加入新項目 - CompareProject] 對話方塊隨即開啟。
按一下 [範本] 底下的 [資料表]。
在 [名稱] 中輸入 InternationalShippers,然後按一下 [加入]。
名為 InternationalShippers 的資料表即會加入至 CompareProject 專案中。 資料表定義隨即出現在 Transact-SQL 編輯器中。
將 InternationalShippers.table.sql 中的 SQL 指令碼變更為下列陳述式:
CREATE TABLE [Sales].[InternationalShippers] ( [ShipperID] [int] NOT NULL IDENTITY(1,1), [CompanyName] [nvarchar] (40) NOT NULL, [Region] [nvarchar] (40) NOT NULL, [Phone] [nvarchar] (24) NULL ) ON [PRIMARY]
按一下 [儲存 InternationalShippers.table.sql]。
在 [結構描述檢視] 中,以滑鼠右鍵按一下 InternationalShippers 資料表,然後按一下 [在方案總管中檢視檔案]。
在 [方案總管] 中,即會反白顯示 InternationalShippers.sql 檔案。
按 F4。
[屬性] 視窗隨即出現,並顯示 InternationalShippers.table.sql 檔案的屬性。 Build Action 屬性會設為 [組建],這表示此檔案包含資料庫物件的定義,而且應該加以剖析及驗證。
比較這兩個結構描述
若要比較這兩個結構描述
指向 [資料] 功能表上的 [結構描述比較],然後按一下 [新增結構描述比較]。
[新增結構描述比較] 對話方塊隨即開啟。
在 [目標結構描述] 中,按一下 [資料庫] 並指定您之前在這個逐步解說中部署的資料庫連接,然後按一下 [確定]。
此資料庫的結構描述會與您變更之專案的結構描述進行比較,且結果會顯示在 [結構描述比較] 視窗中。 在 CompareProject 資料行中,會出現 [Sales].[InternationalShippers] 資料表。 此資料表的狀態為「新增」,而它的更新動作為「建立」。 如果您立刻傳播變更,將會在目標資料庫中建立此資料表。 如需詳細資訊,請參閱以下程序。
若要檢閱及忽略預期的差異
在比較結果清單中,捲動至 [SQL 檔案] 節點。
對於目標資料庫,清單中會顯示兩個狀態為 [遺漏] 的資料列:一列適用於檔案群組檔案,而另一列適用於記錄檔。
按一下每一列的 [更新動作] 資料行,將動作變更為 [略過]。
當您更新資料庫結構描述時,您通常不會想要變更與目標資料庫相關聯的檔案群組檔案或記錄檔。 將動作變更為 [略過],目標資料庫便會繼續使用其目前的檔案。
接著,您可以選擇性地更新目標資料庫,使其符合來源資料庫。
將專案中的變更傳送到資料庫
若要將變更傳播到目標資料庫
按一下 [結構描述比較] 視窗中的 [寫入更新]。
注意事項 如果專案包含一項或多項錯誤,則 [寫入更新] 按鈕可能會停用。 如果發生這種情形,[結構描述比較] 狀態列上便會出現一則訊息。
即會執行列在 [結構描述比較] 視窗中的動作,其中包含 InternationalShippers 資料表的「建立」動作。 這項同步處理會變更資料庫的結構描述,使其符合資料庫專案的結構描述。 當更新作業完成時,會再次比較結構描述並重新整理結果。
當目標結構描述進行更新時,您可以取消作業。請按一下 [資料] 功能表,指向 [結構描述比較],然後按一下 [停止寫入目標]。
警告
由於某些結構描述變更無法在交易範圍內執行,因此如果取消更新作業,則可能會遺失資料。 例如,可能已經卸除目標資料庫中的資料表,做為重新建立的準備。 如果這時取消更新,就可能會遺失該資料表。 如果發生此類資料遺失,您應該再次比較結構描述。