方法 : CLR の SQL Server ユーザー定義型を作成および実行する
更新 : 2007 年 11 月
SQL Server プロジェクトに [ユーザー定義型] を追加して、SQL ユーザー定義型を作成します。正常に配置されると、システム型を使用できるあらゆるコンテキストで、それを使用できます。たとえば、列定義、変数、パラメータ、関数の結果、カーソル、トリガ、およびレプリケーションなどです。ユーザー定義型を使用すると、SQL Server のデータ型システムの機能を拡張したり、複雑な構造型を定義したりできます。
メモ : |
---|
既定では、Microsoft SQL Server では共通言語ランタイム (CLR: Common Language Runtime) 統合機能が無効になっており、SQL Server プロジェクト項目を使用するにはこの機能を有効にする必要があります。CLR 統合を有効にするには、sp_configure ストアド プロシージャの clr enabled オプションを使用します。詳細については、「CLR 統合の有効化」を参照してください。 |
メモ : |
---|
お使いのマシンで、Visual Studio ユーザー インターフェイスの一部の要素の名前や場所が、次の手順とは異なる場合があります。これらの要素は、使用している Visual Studio のエディションや独自の設定によって決まります。詳細については、「Visual Studio の設定」を参照してください。 |
ユーザー定義型の作成
SQL ユーザー定義型を作成するには
既存の SQL Server プロジェクトを開くか、または新しい SQL Server プロジェクトを作成します。詳細については、「方法 : SQL Server プロジェクトを作成する」を参照してください。
[プロジェクト] メニューの [新しい項目の追加] をクリックします。
[新しい項目の追加] ダイアログ ボックスの [ユーザー定義型] を選択します。
新しいユーザー定義型の名前を [ファイル名] に入力します。
ユーザー定義型を定義および作成するコードを追加します。下記の最初の例を参照してください。
メモ : C++ の例は、/clr:safe コンパイラ オプションを使ってコンパイルする必要があります。
Visual Basic および Visual C# の場合は、ソリューション エクスプローラで TestScripts フォルダを開き、Test.sql ファイルをダブルクリックします。
Visual C++ の場合は、ソリューション エクスプローラで debug.sql ファイルをダブルクリックします。
ユーザー定義型を実行するコードを Test.sql (Visual C++ の場合は debug.sql) ファイルに追加します。この手順に続く 2 番目の例を参照してください。
F5 キーを押して、ユーザー定義型をビルド、配置、およびデバッグします。デバッグせずに配置する方法については、「方法 : SQL Server のプロジェクト項目を SQL Server に配置する」を参照してください。
[出力] ウィンドウに表示される結果を確認して、[出力元の表示: データベース出力] を選択します。
使用例
この例では、他の単純型と同じように使用できる Point 型を作成します。Serializable 属性と SqlUserDefinedTypeAttribute 属性の両方を使用して、クラス宣言を装飾します。SqlUserDefinedTypeAttribute の Format プロパティでユーザー定義型の格納形式が決まります。Parse メソッドと ToString メソッドを実装すると、この型に文字列の変換が実装されます。また、この型には、このクラスで表される点の X と Y の値を取得して設定する、2 つのプロパティ プロシージャも実装されます。
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;
}
};
ユーザー定義型 (Point) の実行とテストを行うコードを、プロジェクトの TestScripts フォルダにある Test.sql (Visual C++ の場合は debug.sql) ファイルに追加します。たとえば、新しい型を検証するには、この型を使用するテーブルを作成します。テーブルの作成に 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
参照
処理手順
方法 : CLR の SQL Server ストアド プロシージャを作成および実行する
方法 : CLR の SQL Server トリガを作成および実行する
方法 : CLR の SQL Server の集計を作成および実行する
方法 : CLR の SQL Server ユーザー定義関数を作成および実行する
方法 : CLR の SQL Server ユーザー定義型を作成および実行する
チュートリアル : マネージ コードでのストアド プロシージャの作成
方法 : SQL CLR のストアド プロシージャをデバッグする
概念
SQL Server の CLR 統合の概要 (ADO.NET)
マネージ コードを使用したデータベース オブジェクトの作成の利点
参照
SQL Server プロジェクトおよびデータベース オブジェクトの属性