연습: SQL CLR 사용자 정의 집계 디버깅
업데이트: 2007년 11월
이 항목은 다음 언어에 적용됩니다.
Edition |
Visual Basic |
C# |
C++ |
Web Developer |
---|---|---|---|---|
Express |
||||
Standard |
||||
Pro 및 Team |
표의 범례:
해당 |
|
해당 없음 |
|
명령은 기본적으로 숨겨져 있습니다. |
이 예제에서는 CLR SQL 사용자 정의 집계 함수의 디버깅 방법을 보여 줍니다. AdventureWorks 샘플 데이터베이스에 Concatenate라는 새 CLR SQL 집계 함수를 만듭니다. SQL 문에서 이 함수를 호출하면 입력 매개 변수로 지정된 열의 모든 값이 연결됩니다.
참고: |
---|
표시되는 대화 상자와 메뉴 명령은 실제 설정이나 버전에 따라 도움말에서 설명하는 것과 다를 수 있습니다. 설정을 변경하려면 도구 메뉴에서 설정 가져오기 및 내보내기를 선택합니다. 자세한 내용은 Visual Studio 설정을 참조하십시오. |
CLR SQL 집계 함수를 디버깅하려면
새 SQL Server 프로젝트에서 AdventureWorks 샘플 데이터베이스에 대한 연결을 설정합니다. 자세한 내용은 방법: 데이터베이스에 연결을 참조하십시오.
아래의 첫 번째 예제 섹션에 있는 코드를 사용하여 새 함수를 만들고 이름을 Concatenate.cs로 지정합니다. 자세한 내용은 방법: SQL Server 프로젝트 형식으로 개발을 참조하십시오.
이 함수를 테스트하는 스크립트를 SELECT 문에 추가합니다. 솔루션 탐색기에서 테스트 스크립트 디렉터리를 마우스 오른쪽 단추로 클릭하고 테스트 스크립트 추가를 선택한 다음 이 연습의 두 번째 예제 섹션에 있는 코드를 삽입합니다. Concatenate.sql이라는 이름으로 파일을 저장합니다. 파일 이름을 마우스 오른쪽 단추로 클릭한 다음 기본 디버그 스크립트로 설정을 클릭합니다.
Concatenate.cs에서 if 문의 Accumulate 메서드 안에 중단점을 추가합니다. 이렇게 하려면 텍스트 편집기 창의 왼쪽 회색 여백을 클릭하고 디버그 메뉴에서 시작을 클릭하여 프로젝트를 컴파일, 배포 및 단위 테스트합니다. 중단점에 노란색 화살표로 표시된 지시 포인터가 나타나면 함수가 디버깅되고 있는 것입니다.
다른 디버깅 기능을 사용해 봅니다.
Accumulate 메서드는 Concatenate.sql의 스크립트에서 GROUP BY 절을 구성하는 각 행마다 한 번씩 실행됩니다. 디버그 메뉴에서 한 단계씩 코드 실행을 반복하여 클릭하면 메서드 결과가 생성되는 모습을 볼 수 있습니다.
지역 창에서 현재 처리 중인 상점 이름이 들어 있는 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
참고 항목
작업
방법: CLR SQL Server 집계 만들기 및 실행