共用方式為


逐步解說:偵錯 SQL CLR 使用者定義的彙總

這個主題適用於:

版本

Visual Basic

C#

C++

Web Developer

Express

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

Standard 版

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

Pro/Team 版

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

這個範例將示範如何偵錯 SQL Server Common Language Run-time (SQL CLR) 使用者定義的彙總。 這個範例會在 AdventureWorks 範例資料庫中建立稱為 Concatenate 的新 SQL CLR 彙總函式。 當您在 SQL 陳述式中叫用這個函式時,其會將欄位中所有的值結合在一起指定做為輸入參數。

如果在嘗試偵錯 SQL CLR 物件時出現「已由使用者取消」訊息,您必須手動設定正在執行 Visual Studio 的電腦以及正在執行 SQL Server 的電腦。 如需詳細資訊,請參閱HOW TO:設定您的電腦以啟用 Transact-SQL 和 SQL CLR 偵錯

注意事項注意事項

根據您目前使用的設定或版本,您所看到的對話方塊與功能表指令可能會與 [說明] 中描述的不同。 若要變更設定,請從 [工具] 功能表中選取 [匯入和匯出設定]。 如需詳細資訊,請參閱使用設定

若要偵錯 CLR SQL 彙總函式

  1. 在新的 SQL CLR 專案中,建立與 AdventureWorks 範例資料庫的連接。 如需詳細資訊,請參閱How to: Connect to a Database

  2. 使用下列第一個範例區段的程式碼建立新的函式,並將其命名為 Concatenate.cs。 如需詳細資訊,請參閱How to: Develop with the SQL Server Project Type

  3. 藉由將指令碼包含在 SELECT 陳述式中,加入能夠測試函式的指令碼。 在 [方案總管] 中,以滑鼠右鍵按一下 [TestScripts] 目錄,再選取 [加入測試指令碼],然後插入此逐步解說第二個範例區段中的程式碼。 使用名稱 Concatenate.sql 來儲存檔案。 以滑鼠右鍵按一下檔名,然後按一下 [設定為預設偵錯指令碼]。

  4. 在 if 陳述式的 Accumulate 方法內的 Concatenate.cs 中放置一個中斷點。 若要這麼做,請在 [文字編輯器] 視窗的灰色左邊緣按一下,並按一下 [偵錯] 功能表上的 [啟動] 來編譯和部署專案,並進行單元測試。 當中斷點上出現以黃色箭頭表示的指令指標時,即表示您正在偵錯函式。

  5. 嘗試不同的偵錯功能。

    1. Concatenate.sql 內的指令碼中,每個構成 GROUP BY 子句的資料列都會執行 Accumulate 方法一次。 重複按 [偵錯] 功能表中的 [偵錯],您便可以監看方法結果的建置方式。

    2. 在 [區域變數] 視窗中,開啟包含目前正在處理中之存放區名稱的變數 value。

    3. 按一下變數 this。 這個函式會傳回子節點 intermediateResult,而其包含目前存放區在內的所有存放區名稱,並且會以逗號分隔的方式串連在一起。

    4. 在 [文字編輯器] 內,按兩下 intermediateResult 變數來選取它。 將 intermediateResult 拖曳到 [監看式] 視窗,並將它放到視窗內的任一位置。 該變數現在將加入被監看變數的清單內。

    5. 逐步執行這個方法幾次。 intermediateResult 的值將會在每次逐步執行方法時變更,並且將額外的存放區名稱串連到結尾。

    6. 按一下以移除該中斷點,然後將新中斷點加入 Terminate 方法內的第一個陳述式中。 這個方法會將結果傳回呼叫端。 若要逐步執行,請在 [偵錯] 功能表上按一下 [啟動]。 現在您可以按一下 [偵錯] 功能表上的 [逐步執行] 來逐步執行。 當您叫用 return 陳述式時停止。

    7. 再按一次 [繼續],以完成此函式的偵錯動作。

範例

以下是這個範例使用的彙總函式程式碼。

using System;
using System.Data.Sql;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.IO;
using System.Text;
[Serializable]
[SqlUserDefinedAggregate( 
    //use CLR serialization to serialize the intermediate result. 
    Format.UserDefined, 
    //Optimizer property: 
    IsInvariantToNulls=true,
    //Optimizer property: 
    IsInvariantToDuplicates=false,
    //Optimizer property: 
    IsInvariantToOrder=false,
    //Maximum size in bytes of persisted value: 
    MaxByteSize=8000)
] 
public class Concatenate: IBinarySerialize 
{ 
    /// <summary> 
    /// Variable holds intermediate result of the concatenation 
    /// </summary> 
    private StringBuilder intermediateResult; 
    /// <summary> 
    /// Initialize the internal data structures 
    /// </summary> 
    public void Init( ) 
    { 
        intermediateResult = new StringBuilder(); 
    } 
    /// <summary> 
    /// Accumulate the next value, nop if the value is null 
    /// </summary> 
    /// <param name="value"></param> 
    public void Accumulate(SqlString value) 
    { 
        if(value.IsNull) 
        { 
            return; 
        } 
        intermediateResult.Append(value.Value).Append(','); 
    } 
    /// <summary> 
    /// Merge the partially computed aggregate with this aggregate. 
    /// </summary> 
    /// <param name="other"></param> 
    public void Merge( Concatenate other) 
    { 
        intermediateResult.Append(other.intermediateResult); 
    } 
    /// <summary> 
    /// Called at end of aggregation, to return results. 
    /// </summary> 
    /// <returns></returns> 
    public SqlString Terminate() 
    { 
        string output = string.Empty; 
        //Delete the trailing comma, if any .
        if (intermediateResult != null && intermediateResult.Length > 0) 
            output = intermediateResult.ToString(0, intermediateResult.Length-1); 
        return new SqlString(output); 
    } 
    public void Read(BinaryReader r) 
    { 
        intermediateResult = new StringBuilder(r.ReadString()); 
    } 
    public void Write(BinaryWriter w) 
    { 
        w.Write(intermediateResult.ToString()); 
    } 
}

此為呼叫函式的測試指令碼。

SELECT scu.SalesPersonID, dbo.Concatenate(sst.Name)
FROM Sales.Customer as scu 
INNER JOIN Sales.Store as sst
    ON scu.CustomerID    = sst.CustomerID
INNER JOIN Sales.SalesPerson as spr
    ON scu.SalesPersonID = spr.SalesPersonID
WHERE    scu.SalesPersonID = 283
GROUP BY scu.SalesPersonID

請參閱

工作

HOW TO:使用 Common Language Run-time 整合建立和執行 SQL Server 彙總