방법: CLR SQL Server 사용자 정의 형식 만들기 및 실행

업데이트: 2007년 11월

사용자 정의 형식을 SQL Server 프로젝트에 추가하여 SQL 사용자 정의 형식을 만듭니다. 성공적으로 배포한 뒤에는 시스템 형식을 사용할 수 있는 모든 컨텍스트에서 이 형식을 사용할 수 있습니다. 이러한 컨텍스트에는 열 정의, 변수, 매개 변수, 함수 결과, 커서, 트리거, 복제 등이 있습니다. 사용자 정의 형식은 사용자에게 SQL Server 데이터 형식 시스템의 확장성을 제공하며 사용자가 복잡한 구조화된 형식을 정의할 수 있도록 합니다.

참고:

기본적으로 CLR(공용 언어 런타임) 통합 기능은 Microsoft SQL Server에서 해제되어 있으며 SQL Server 프로젝트 항목을 사용하려면 이 기능을 사용하도록 설정해야 합니다. CLR 통합 기능을 사용하도록 설정하려면 sp_configure 저장 프로시저의 clr enabled 옵션을 사용합니다. 자세한 내용은 CLR 통합 설정을 참조하십시오.

참고:

다음 지침처럼 컴퓨터에서 Visual Studio 사용자 인터페이스 요소 일부에 대한 이름이나 위치를 다르게 표시할 수 있습니다. 이러한 요소는 사용하는 Visual Studio 버전 및 설정에 따라 결정됩니다. 자세한 내용은 Visual Studio 설정을 참조하십시오.

사용자 정의 형식 만들기

SQL 사용자 정의 형식을 만들려면

  1. 기존의 SQL Server 프로젝트를 열거나 새 프로젝트를 만듭니다. 자세한 내용은 방법: SQL Server 프로젝트 만들기를 참조하십시오.

  2. 프로젝트 메뉴에서 새 항목 추가를 선택합니다.

  3. 새 항목 추가 대화 상자에서 사용자 정의 형식을 선택합니다.

  4. 새 사용자 정의 형식의 이름을 입력합니다.

  5. 사용자 정의 형식을 정의하고 만드는 코드를 추가합니다. 이 절차 뒤의 첫 번째 예제를 참조하십시오.

    참고:

    C++ 예제는 /clr:safe 컴파일러 옵션을 사용하여 컴파일해야 합니다.

  6. Visual Basic 및 Visual C#의 경우 솔루션 탐색기에서 TestScripts 폴더를 열고 Test.sql 파일을 두 번 클릭합니다.

    Visual C++의 경우 솔루션 탐색기에서 debug.sql 파일을 두 번 클릭합니다.

  7. Test.sql(Visual C++의 경우 debug.sql) 파일에 사용자 정의 형식을 실행하는 코드를 추가합니다. 이 절차 뒤의 두 번째 예제를 참조하십시오.

  8. F5 키를 눌러 사용자 정의 형식을 빌드, 배포 및 디버깅합니다. 디버깅하지 않고 배포하는 방법에 대한 자세한 내용은 방법: SQL Server에 SQL Server 프로젝트 항목 배포를 참조하십시오.

  9. 출력 창에 표시되는 결과를 보고 다음에서 출력 보기: 데이터베이스 출력을 선택합니다.

예제

이 예제에서는 다른 단순 형식과 마찬가지 방법으로 사용할 수 있는 Point 형식을 만듭니다. 클래스 선언은 Serializable 및 SqlUserDefinedTypeAttribute 특성으로 데코레이팅됩니다. SqlUserDefinedTypeAttribute의 Format 속성에 따라 사용자 정의 형식의 저장소 형식이 결정됩니다. 이 형식은 Parse 및 ToString 메서드를 구현하여 문자열 변환을 구현합니다. 또한 이 클래스로 표현되는 점의 X 및 Y 값을 가져오고 설정하는 두 개의 속성 프로시저도 구현합니다.

Imports System
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server

<Serializable()> _
<SqlUserDefinedType(Format.Native)> _
Public Structure Point
    Implements INullable

    Private m_x As Int32
    Private m_y As Int32
    Private is_Null As Boolean


    Public Property X() As Int32
        Get
            Return (Me.m_x)
        End Get
        Set(ByVal Value As Int32)
            m_x = Value
        End Set
    End Property


    Public Property Y() As Int32
        Get
            Return (Me.m_y)
        End Get
        Set(ByVal Value As Int32)
            m_y = Value
        End Set
    End Property


    Public ReadOnly Property IsNull() As Boolean Implements INullable.IsNull
        Get
            Return is_Null
        End Get
    End Property


    Public Shared ReadOnly Property Null() As Point
        Get
            Dim pt As Point = New Point
            pt.is_Null = True
            Return pt
        End Get
    End Property


    Public Overrides Function ToString() As String
        If Me.IsNull() Then
            Return Nothing
        Else
            Return Me.m_x & ":" & Me.m_y
        End If
    End Function


    Public Shared Function Parse(ByVal s As SqlString) As Point
        If s = SqlString.Null Then
            Return Null
        End If

        If s.ToString() = SqlString.Null.ToString() Then
            Return Null
        End If

        If s.IsNull Then
            Return Null
        End If

        'Parse input string here to separate out coordinates
        Dim str As String = Convert.ToString(s)
        Dim xy() As String = str.Split(":"c)

        Dim pt As New Point()
        pt.X = CType(xy(0), Int32)
        pt.Y = CType(xy(1), Int32)
        Return (pt)
    End Function


    Public Function Quadrant() As SqlString

        If m_x = 0 And m_y = 0 Then
            Return "centered"
        End If

        Dim stringResult As String = ""

        Select Case m_x
            Case 0
                stringResult = "center"
            Case Is > 0
                stringResult = "right"
            Case Is < 0
                stringResult = "left"
        End Select

        Select Case m_y
            Case 0
                stringResult = stringResult & " center"
            Case Is > 0
                stringResult = stringResult & " top"
            Case Is < 0
                stringResult = stringResult & " bottom"
        End Select

        Return stringResult
    End Function
End Structure
using System;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

[Serializable()]
[SqlUserDefinedType(Format.Native)]
public struct Point : INullable
{
    private Int32 m_x;
    private Int32 m_y;
    private bool is_Null;


    public Int32 X
    {
        get
        {
            return (this.m_x);
        }
        set
        {
            m_x = value;
        }
    }


    public Int32 Y
    {
        get
        {
            return (this.m_y);
        }
        set
        {
            m_y = value;
        }
    }


    public bool IsNull
    {
        get
        {
            return is_Null;
        }
    }


    public static Point Null
    {
        get
        {
            Point pt = new Point();
            pt.is_Null = true;
            return (pt);
        }
    }


    public override string ToString()
    {
        if (this.IsNull)
        {
            return "NULL";
        }
        else
        {
            return this.m_x + ":" + this.m_y;
        }
    }


    public static Point Parse(SqlString s)
    {
        if (s.IsNull)
        {
            return Null;
        }

        // Parse input string here to separate out coordinates
        string str = Convert.ToString(s);
        string[] xy = str.Split(':');

        Point pt = new Point();
        pt.X = Convert.ToInt32(xy[0]);
        pt.Y = Convert.ToInt32(xy[1]);
        return (pt);
    }


    public SqlString Quadrant()
    {
        if (m_x == 0 && m_y == 0)
        {
            return "centered";
        } 

        SqlString stringReturn = "";

        if (m_x == 0)
        {
            stringReturn = "center";
        }
        else if (m_x > 0)
        {
            stringReturn = "right";
        } 
        else if (m_x < 0)
        {
            stringReturn = "left";
        }

        if (m_y == 0) 
        {
            stringReturn = stringReturn + " center";
        }
        else if (m_y > 0)
        {
            stringReturn = stringReturn + " top";
        }
        else if (m_y < 0)
        {
            stringReturn = stringReturn + " bottom";
        }

        return stringReturn;
    }
}
#include "stdafx.h"

#using <System.dll>
#using <System.Data.dll>
#using <System.Xml.dll>

using namespace System;
using namespace System::Data;
using namespace System::Data::Sql;
using namespace System::Data::SqlTypes;
using namespace Microsoft::SqlServer::Server;

// In order to debug your User-Defined Types, add the following to your debug.sql file:
//
// CREATE TABLE test_table (column1 Point)
//
// INSERT INTO test_table (column1) VALUES ('1:2')
// INSERT INTO test_table (column1) VALUES ('-2:3')
// INSERT INTO test_table (column1) VALUES ('-3:-4')
//
// SELECT column1.Quadrant() FROM test_table
//
// DROP TABLE test_table
//
[Serializable]
[SqlUserDefinedType(Format::Native)]
public value struct Point : public INullable
{
private:
    Int32 m_x;
    Int32 m_y;
    bool is_Null;

public:
    property Int32 X
    {
        Int32 get() { return (this->m_x); }
        void set(Int32 value) { m_x = value; }
    }

    property Int32 Y
    {
        Int32 get() { return (this->m_y); }
        void set(Int32 value) { m_y = value; }
    }

    virtual property bool IsNull
    {
        bool get() { return is_Null; }
    }

    static property Point Null
    {
        Point get()
        {
            Point pt;
            pt.is_Null = true;
            return (pt);
        }
    }

    virtual String ^ToString() override
    {
        if (this->IsNull)
        {
            return "NULL";
        }
        else
        {
            return this->m_x + ":" + this->m_y;
        }
    }


    static Point Parse(SqlString s)
    {
        if (s.IsNull)
        {
            return Null;
        }

        // Parse input string here to separate out coordinates
        String ^str = Convert::ToString(s);
        array<String ^> ^xy = str->Split(':');

        Point pt;
        pt.X = Convert::ToInt32(xy[0]);
        pt.Y = Convert::ToInt32(xy[1]);
        return (pt);
    }


    SqlString Quadrant()
    {
        if (m_x == 0 && m_y == 0)
        {
            return "centered";
        }

        SqlString stringReturn = "";

        if (m_x == 0)
        {
            stringReturn = "center";
        }
        else if (m_x > 0)
        {
            stringReturn = "right";
        }
        else if (m_x < 0)
        {
            stringReturn = "left";
        }

        if (m_y == 0)
        {
            stringReturn = stringReturn + SqlString(" center");
        }
        else if (m_y > 0)
        {
            stringReturn = stringReturn + SqlString(" top");
        }
        else if (m_y < 0)
        {
            stringReturn = stringReturn + SqlString(" bottom");
        }

        return stringReturn;
    }
};

프로젝트의 TestScripts 폴더에 있는 Test.sql(Visual C++의 경우 debug.sql) 파일에 사용자 정의 형식(Point)을 실행 및 테스트하는 코드를 추가합니다. 예를 들어, 새 형식을 검사하려면 이 형식을 사용하는 테이블을 만듭니다. 다음 예제에서는 테이블을 만들 때 Point 형식을 사용하는 방법을 보여 줍니다.

CREATE TABLE test_table (column1 Point)
go

INSERT INTO test_table (column1) VALUES ('1:2')
INSERT INTO test_table (column1) VALUES ('-2:3')
INSERT INTO test_table (column1) VALUES ('-3:-4')

select column1.Quadrant() from test_table

참고 항목

작업

방법: SQL Server 프로젝트 만들기

방법: CLR SQL Server 저장 프로시저 만들기 및 실행

방법: CLR SQL Server 트리거 만들기 및 실행

방법: CLR SQL Server 집계 만들기 및 실행

방법: CLR SQL Server 사용자 정의 함수 만들기 및 실행

방법: CLR SQL Server 사용자 정의 형식 만들기 및 실행

연습: 관리 코드로 저장 프로시저 만들기

방법: SQL CLR 저장 프로시저 디버깅

개념

SQL Server CLR 통합 소개

관리 코드를 사용하여 데이터베이스 개체를 만드는 경우의 이점

SQL Server 프로젝트에 대한 항목 템플릿

참조

SQL Server 프로젝트 및 데이터베이스 개체의 특성

기타 리소스

SQL CLR 데이터베이스 디버깅