共用方式為


逐步解說:比較資料庫與資料庫專案的結構描述

這個主題適用於:

Visual Studio Ultimate

Visual Studio Premium

Visual Studio Professional 

Visual Studio Express

標題適用於 標題適用於 標題不適用於 標題不適用於

在此逐步解說中,您會使用 Visual Studio 來比較「資料庫專案」(Database Project) 的「結構描述」(Schema) 與資料庫的結構描述。在考量您的小組使用資料庫專案與資料庫的方式下,您可能會想要複製其中一方的結構描述變更。 當小組在進行資料庫開發週期時,您可能會遇到下列典型案例:

  • 以專案為來源而資料庫為目標。您可以使用資料庫專案來開發或維護資料庫。 在您變更專案的結構描述之後,您會將這些變更複製到裝載於開發用伺服器上的資料庫。 之後,您的小組可以將此資料庫部署至實際執行伺服器。

    您在此逐步解說中執行的比較會從結構描述差異產生資料定義語言 (DDL) 指令碼。 然後您可以使用此指令碼,將資料庫專案的全部或部分套用到此資料庫。 如需詳細資訊,請參閱將專案中的變更傳送到資料庫。

  • 以資料庫為來源而專案為目標。可能會在實際執行資料庫的結構描述中找到錯誤,或是該結構描述可能過期且需要更新。 這項探索可能會要求小組將緊急的更新套用到資料庫。 為了讓專案與資料庫保持同步,您可以接著將更新匯入到資料庫專案中。 如需詳細資訊,請參閱 HOW TO:將資料庫的更新匯入到資料庫專案

這個逐步解說將說明下列工作:

設定階段

  1. 建立資料庫專案。 新的專案一開始是空的。

  2. 從指令碼匯入資料庫結構描述。

  3. 設定、建置及部署資料庫專案到資料庫伺服器。 資料庫與專案具有相同的結構描述。

實際執行階段

  1. 將資料表加入到資料庫專案。 您會新增名為 InternationalShippers 的資料表,此資料表有三個資料行。

  2. 比較這兩個結構描述。 在這項比較中,您會將資料庫專案指定為來源,並將資料庫指定為目標。 因此,結果會將 InternationalShippers 資料表顯示為資料庫專案中的新資料表。

  3. 將專案中的變更傳送到資料庫。 您可以將資料庫專案中的新 InternationalShippers 資料表傳播至已部署的資料庫。 您若遵循此程序,便會覆寫部分的範例資料庫。

    注意事項注意事項

    您也可以將資料庫中的變更傳播至資料庫專案。 如需詳細資訊,請參閱 HOW TO:將資料庫的更新匯入到資料庫專案

必要條件

您需要下列應用程式和權限,才能完成此逐步解說:

  • SQL Server 2008

  • 在目標資料庫伺服器上建立和更新資料庫的權限

  • Visual Studio Premium 或 Visual Studio Ultimate

設定階段

建立資料庫專案

若要建立資料庫專案

  1. 在 [檔案] 功能表上,指向 [新增],然後按一下 [專案]。

    [新增專案] 對話方塊隨即開啟。

  2. 展開 [已安裝的範本] 底下的 [資料庫] 節點,然後按一下 [SQL Server]。

  3. 在範本清單中,按一下 [SQL Server 2008 資料庫專案]。

  4. 在 [名稱] 中輸入 CompareProject,然後按一下 [確定]。

    空的 CompareProject 專案會隨即開啟並出現在 [方案總管] 中。

從指令碼匯入資料庫結構描述

若要建立您可以從中匯入結構描述的指令碼

  1. 在 [檔案] 功能表上指向 [新增],然後按一下 [檔案]。

    [新增檔案] 對話方塊隨即開啟。

  2. 按一下 [分類] 清單中的 [一般] (若尚未反白顯示)。

  3. 在 [範本] 清單中,按一下 [Sql 檔],然後再按一下 [開啟]。

    Transact-SQL 編輯器隨即開啟。

  4. 複製下列程式碼,並將其貼入 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
    
  5. 按一下 [檔案] 功能表上的 [另存 SqlQuery_1.sql]。

    [另存新檔] 對話方塊隨即開啟。

  6. 在 [物件名稱] 中,輸入 SampleImportScript.sql。

    您可以將此檔案儲存至電腦上的任何位置。 請記下這個位置,因為您必須用於下一個程序中。

  7. 按一下 [儲存]。

  8. 在 [檔案] 功能表上,按一下 [關閉方案]。

    接著,您要建立資料庫專案,並從您已建立的指令碼匯入結構描述。

若要從指令碼匯入資料庫結構描述

  1. 按一下 [專案] 功能表上的 [匯入資料庫指令碼]。

  2. 閱讀完 [歡迎] 頁面之後,請按 [下一步]。

  3. 按一下 [瀏覽],並瀏覽至您儲存 SampleImportScript.sql 檔案的位置。

  4. 按兩下 SampleImportScript.sql 檔案,然後按一下 [完成]。

    如此就會匯入指令碼,而且該指令碼中定義的物件會加入至資料庫專案。

  5. 檢閱摘要,然後按一下 [完成]。

設定、建置和部署資料庫專案

這些程序會在「隔離的開發環境」(Isolated Development Environment) (或沙箱) 中建立有已匯入結構描述的資料庫,以便您開發和測試資料庫。

若要設定並建置資料庫專案

  1. 在 [方案總管] 中,按一下 CompareProject 專案。

  2. 按一下 [專案] 功能表上的 [CompareProject 屬性]。

    CompareProject 專案的屬性隨即出現。

  3. 按一下 [部署] 索引標籤。

  4. 在 [部署動作] 清單中,按一下 [建立部署指令碼 (.sql) 並部署到資料庫]。

  5. 在 [目標資料庫設定] 中,按一下 [編輯]。

  6. 在 [連接屬性] 對話方塊中,針對您要使用的資料庫設定其連接屬性,然後按一下 [確定]。

    [目標連接] 方塊會顯示正確的連接字串。

    警告

    您應該在測試伺服器、程式開發伺服器或本機電腦上建立資料庫。 您不應該使用實際執行伺服器。

  7. 在 [目標資料庫名稱] 方塊中輸入 CompareProjectDB。

  8. 在 [檔案] 功能表上按一下 [全部儲存]。

  9. 在 [建置] 功能表上,按一下 [建置方案]。

    部署指令碼是根據您剛設定的專案屬性而建置。 建置的狀態會出現在 [輸出] 視窗中,而且 [組建: 1 成功或最新狀態] 會出現在最後一行。

若要部署資料庫專案

  1. 在 [方案總管] 中,按一下 CompareProject 專案。

  2. 按一下 [建置] 功能表上的 [部署 CompareProject]。

    此外,您也可以用滑鼠右鍵按一下 [方案總管] 中的專案,然後按一下 [部署]。

    警告

    您應該針對測試伺服器、程式開發伺服器或本機電腦執行這項部署, 您不應該使用實際執行伺服器。

    資料庫專案即會部署到新的資料庫。 部署的狀態會出現在 [輸出] 視窗中,而且 [部署成功] 會出現在最後一行。

實際執行階段

將資料表加入到資料庫專案

若要將資料表加入至專案

  1. 按一下 [檢視] 功能表上的 [資料庫結構描述檢視]。

    [結構描述檢視] 隨即開啟,並顯示 CompareProject 專案的結構描述。

  2. 在 [結構描述檢視] 中,展開 CompareProject 節點,然後展開 [結構描述] 節點。

  3. 以滑鼠右鍵按一下 [Sales],然後指向 [加入],再按一下 [資料表]。

    [加入新項目 - CompareProject] 對話方塊隨即開啟。

  4. 按一下 [範本] 底下的 [資料表]。

  5. 在 [名稱] 中輸入 InternationalShippers,然後按一下 [加入]。

    名為 InternationalShippers 的資料表即會加入至 CompareProject 專案中。 資料表定義隨即出現在 Transact-SQL 編輯器中。

  6. 將 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]
    
  7. 按一下 [儲存 InternationalShippers.table.sql]。

  8. 在 [結構描述檢視] 中,以滑鼠右鍵按一下 InternationalShippers 資料表,然後按一下 [在方案總管中檢視檔案]。

    在 [方案總管] 中,即會反白顯示 InternationalShippers.sql 檔案。

  9. 按 F4。

    [屬性] 視窗隨即出現,並顯示 InternationalShippers.table.sql 檔案的屬性。 Build Action 屬性會設為 [組建],這表示此檔案包含資料庫物件的定義,而且應該加以剖析及驗證。

比較這兩個結構描述

若要比較這兩個結構描述

  1. 指向 [資料] 功能表上的 [結構描述比較],然後按一下 [新增結構描述比較]。

  2. [新增結構描述比較] 對話方塊隨即開啟。

  3. 在 [目標結構描述] 中,按一下 [資料庫] 並指定您之前在這個逐步解說中部署的資料庫連接,然後按一下 [確定]。

    此資料庫的結構描述會與您變更之專案的結構描述進行比較,且結果會顯示在 [結構描述比較] 視窗中。 在 CompareProject 資料行中,會出現 [Sales].[InternationalShippers] 資料表。 此資料表的狀態為「新增」,而它的更新動作為「建立」。 如果您立刻傳播變更,將會在目標資料庫中建立此資料表。 如需詳細資訊,請參閱以下程序。

若要檢閱及忽略預期的差異

  1. 在比較結果清單中,捲動至 [SQL 檔案] 節點。

    對於目標資料庫,清單中會顯示兩個狀態為 [遺漏] 的資料列:一列適用於檔案群組檔案,而另一列適用於記錄檔。

  2. 按一下每一列的 [更新動作] 資料行,將動作變更為 [略過]。

    當您更新資料庫結構描述時,您通常不會想要變更與目標資料庫相關聯的檔案群組檔案或記錄檔。 將動作變更為 [略過],目標資料庫便會繼續使用其目前的檔案。

    接著,您可以選擇性地更新目標資料庫,使其符合來源資料庫。

將專案中的變更傳送到資料庫

若要將變更傳播到目標資料庫

  • 按一下 [結構描述比較] 視窗中的 [寫入更新]。

    注意事項注意事項

    如果專案包含一項或多項錯誤,則 [寫入更新] 按鈕可能會停用。 如果發生這種情形,[結構描述比較] 狀態列上便會出現一則訊息。

    即會執行列在 [結構描述比較] 視窗中的動作,其中包含 InternationalShippers 資料表的「建立」動作。 這項同步處理會變更資料庫的結構描述,使其符合資料庫專案的結構描述。 當更新作業完成時,會再次比較結構描述並重新整理結果。

    當目標結構描述進行更新時,您可以取消作業。請按一下 [資料] 功能表,指向 [結構描述比較],然後按一下 [停止寫入目標]。

    警告

    由於某些結構描述變更無法在交易範圍內執行,因此如果取消更新作業,則可能會遺失資料。 例如,可能已經卸除目標資料庫中的資料表,做為重新建立的準備。 如果這時取消更新,就可能會遺失該資料表。 如果發生此類資料遺失,您應該再次比較結構描述。

請參閱

工作

HOW TO:比較資料庫結構描述

HOW TO:比較及同步處理兩個資料庫的資料

概念

比較和同步處理資料庫結構描述

使用參考資料庫中的資料比較和同步處理一個或多個資料表中的資料