このトピックの内容は、次の製品に該当します。
エディション |
Visual Basic |
C# |
C++ |
Web Developer |
---|---|---|---|---|
Express |
![]() |
![]() |
![]() |
![]() |
[標準] |
![]() |
![]() |
![]() |
![]() |
Pro/Team |
![]() |
![]() |
![]() |
![]() |
この例では、SQL Server 共通言語ランタイム (SQL CLR) のユーザー定義集計をデバッグする方法について説明します。 この例により、AdventureWorks サンプル データベースに Concatenate という、新しい SQL CLR 集計関数が作成されます。 SQL ステートメントでこの関数を呼び出すと、入力パラメーターで指定した列の値がすべて連結されます。
SQL CLR オブジェクトをデバッグしようとしたときに "ユーザーによってキャンセルされました" というメッセージが表示された場合は、Visual Studio を実行しているコンピューターと SQL Server を実行しているコンピューターの両方を手動で構成する必要があります。 詳細については、「方法: Transact-SQL デバッグと SQL CLR デバッグを実行するためのコンピューターを構成する」を参照してください。
注意
実際に画面に表示されるダイアログ ボックスとメニュー コマンドは、アクティブな設定またはエディションによっては、ヘルプの説明と異なる場合があります。 設定を変更するには、[ツール] メニューの [設定のインポートとエクスポート] をクリックします。 詳細については、「設定の操作」を参照してください。
CLR SQL 集計関数をデバッグするには
新しい SQL CLR プロジェクトで、AdventureWorks サンプル データベースへの接続を確立します。 詳細については、「方法 : データベースへの接続します。」を参照してください。
この後の最初のサンプルにあるコードを使用して、新しい関数を作成し、Concatenate.cs と名前を付けます。 詳細については、「方法 : SQL Server プロジェクトの種類と開発します。」を参照してください。
SELECT ステートメントに含めて、関数をテストするスクリプトを追加します。 ソリューション エクスプローラーの [TestScripts] ディレクトリを右クリックし、[テスト スクリプトの追加] をクリックして、このチュートリアルの 2 つ目のサンプルにあるコードを挿入します。 ファイル名に Concatenate.sql と名前を付けて、保存します。 ファイル名を右クリックし、[既定のデバッグ スクリプトの設定] をクリックします。
if ステートメントの Accumulate メソッド内にある Concatenate.cs にブレークポイントを設定します。 そのためには、テキスト エディター ウィンドウの網かけの左端余白をクリックします。次に [デバッグ] メニューの [デバッグ開始] をクリックして、プロジェクトのコンパイル、配置、単体テストを実行します。 黄色の矢印で表される命令ポインターがブレークポイントに表示されて、関数のデバッグが行われます。
いろいろなデバッグ機能を試してください。
Concatenate.sql のスクリプト内の GROUP BY 句を構成する各行について、Accumulate メソッドが 1 回実行されます。 [デバッグ] メニューの [ステップ イン] を繰り返しクリックすることにより、このメソッドの結果が生成される過程を観察できます。
[ローカル] ウィンドウで、変数 value を開きます。この変数には、現在処理中のストア名が含まれます。
変数 this をクリックします。 この関数から子ノード intermediateResult が返されます。この子ノードには、現在のものまでのすべてのストア名がコンマ区切りで 1 つに連結されています。
テキスト エディターで、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