逐步解說:偵錯 SQL CLR 使用者定義的彙總
更新:2007 年 11 月
這個主題適用於:
版本 |
Visual Basic |
C# |
C++ |
Web Developer |
---|---|---|---|---|
Express 版 |
||||
Standard 版 |
||||
Pro/Team 版 |
表格圖例:
套用 |
|
不套用 |
|
預設隱藏的命令。 |
這個範例將示範如何偵錯 CLR SQL 使用者定義的彙總。這個範例會在 AdventureWorks 範例資料庫中建立稱為 Concatenate 的新 CLR SQL 彙總函式。當您在 SQL 陳述式中叫用這個函式時,其會將欄位中所有的值結合在一起指定做為輸入參數。
注意事項: |
---|
您所看見的對話方塊與功能表命令可能會與 [說明] 中所描述的有所不同,視您所使用的設定或版本而定。若要變更設定,請從 [工具] 功能表中選擇 [匯入和匯出設定]。如需詳細資訊,請參閱 Visual Studio 設定。 |
若要偵錯 CLR SQL 彙總函式
在新的 SQL Server 專案中,建立與 AdventureWorks 範例資料庫的連線。如需詳細資訊,請參閱 HOW TO:連接資料庫。
使用下列第一個範例區段的程式碼建立新的函式,並將其命名為 Concatenate.cs。如需詳細資訊,請參閱 HOW TO:使用 SQL Server 專案類型開發。
藉由將指令碼包含在 SELECT 陳述式中,加入能夠測試函式的指令碼。在 [方案總管] 中,以滑鼠右鍵按一下 [TestScripts] 目錄,再選取 [加入測試指令碼],然後插入此逐步解說第二個範例區段中的程式碼。使用名稱 Concatenate.sql 來儲存檔案。以滑鼠右鍵按一下檔名,然後按一下 [設定為預設偵錯指令碼]。
在 if 陳述式 Accumulate 方法中的 Concatenate.cs放置一個中斷點。若要這麼做,請在 [文字編輯器] 視窗的灰色左邊緣按一下,並按一下 [偵錯] 功能表上的 [啟動] 來編譯和部署專案,並進行單元測試。當中斷點上出現以黃色箭頭表示的指令指標時,即表示您正在偵錯函式。
嘗試不同的偵錯功能。
Concatenate.sql 內的指令碼中,每個構成 GROUP BY 子句的資料列都會執行 Accumulate 方法一次。重複按 [偵錯] 功能表中的 [偵錯],您便可以監看方法結果的建置方式。
在 [區域變數] 視窗中,開啟包含目前正在處理中之存放區名稱的變數 value。
按一下變數 this。這個函式會傳回子節點 intermediateResult,而其包含目前存放區在內的所有存放區名稱,並且會以逗號分隔的方式串連在一起。
在 [文字編輯器] 內,按兩下 intermediateResult 變數來選取它。將 intermediateResult 拖曳到 [監看式] 視窗,並將它放到視窗內的任一位置。該變數現在將加入被監看變數的清單內。
逐步執行這個方法幾次。intermediateResult 的值將會在每次逐步執行方法時變更,並且將額外的存放區名稱串連到結尾。
按一下以移除該中斷點,然後將新中斷點加入 Terminate 方法內的第一個陳述式中。這個方法會將結果傳回呼叫端。若要逐步執行,請在 [偵錯] 功能表上按一下 [啟動]。現在您可以按一下 [偵錯] 功能表上的 [逐步執行] 來逐步執行。當您叫用 return 陳述式時停止。
再按一次 [繼續],以完成此函式的偵錯動作。
範例
以下是這個範例使用的彙總函式程式碼。
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:建立及執行 CLR SQL Server 彙總