web-dev-qa-db-ja.com

SQL Serverはカスタムドメインをサポートしていますか?

PostgreSQLは、SQL 2011ワーキングドラフト仕様のDOMAIN仕様 をサポートしています。

ドメインは、データ型を指定できる特定の場所で、データ型の代替として指定できる名前付きのユーザー定義オブジェクトです。ドメインは、データ型、場合によってはデフォルトオプション、および0個以上の(ドメイン)制約で構成されます。

これにより、 のような本当にクールなことを行うことができますdomainを実装して、大文字と小文字を区別しないテキストでメールのHTML5-spec type データベースにアクセスするすべてのクライアントに、挿入されたデータの整合性チェックがあることを保証します。

CREATE DOMAIN email AS citext
  CHECK ( value ~ '^[a-zA-Z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$' );

SQL Serverは、トリガーシステムの外部でこのような機能をサポートしていますか?

8
Evan Carroll

SQLCLRは、完全にカスタムのデータ型を作成するための表面領域を提供します。実際、これがSQL Serverが幾何データ型と階層データ型をサポートする方法です。

SQLCLRはMicrosoft.Net共通中間言語に基づいているため、SQLCLRデータ型にはさまざまな制約が可能です。たとえば、データ検証コードの一部としてMXレコードのDNSをクエリすることで、メールアドレスが有効なドメインからのものであることを簡単に確認できます。

SQL Serverは、IsByteOrdered:=Trueが設定されている限り、CLR UDTにインデックスを付けることができます。そのような多くのプロパティがあり、SQL ServerがUDTを使用する方法に影響を与えるように変更できます。インデックスに必要な同等性マッチングの場合、SQL Serverはページに格納されているバイナリ値を確認するだけです。つまり、UDTコードを確認する必要はまったくありません。

ドメインスペースの有効性をチェックするSQLCLR User-defined-typeの例として、次のひどい概念実証VB.Netコードを記述しました。

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

<Serializable()> _
<Microsoft.SqlServer.Server.SqlUserDefinedType(Format.UserDefined, IsByteOrdered:=True, MaxByteSize:=320, ValidationMethodName:="ValidateEmailAddress")> _
Public Structure EmailType
    Implements INullable
    Implements IBinarySerialize

    Private m_Null As Boolean
    Private m_EmailAddress As String

    Public Function ValidateEmailAddress() As Boolean
        'is the email address valid?
        If Me.IsValidDomain Then
            Return True
        Else
            Return False
        End If
    End Function

    Public Overrides Function ToString() As String
        Return Me.m_EmailAddress
    End Function

    Public ReadOnly Property IsNull() As Boolean Implements INullable.IsNull
        Get
            ' Put your code here
            If Me.m_EmailAddress Is Nothing Then
                Me.m_Null = True
            Else
                Me.m_Null = False
            End If
            Return m_Null
        End Get
    End Property

    Public Shared ReadOnly Property Null As EmailType
        Get
            Dim h As New EmailType
            h.m_Null = True
            Return h
        End Get
    End Property

    'called when SQL Server passes in a SqlString value to the UDT
    Public Shared Function Parse(ByVal s As SqlString) As EmailType
        If s.IsNull Then
            Return Null
        End If

        Dim u As New EmailType

        u.m_EmailAddress = CType(s, String)
        If u.ValidateEmailAddress = False Then
            Throw New Exception("Invalid Email Address")
        End If
        Return u
    End Function

    Public Function IsValidDomain() As Boolean
        Dim iAtSign As Int32 = Microsoft.VisualBasic.Strings.InStr(Me.m_EmailAddress, "@")
        Dim iDomainLength As Int32 = Microsoft.VisualBasic.Strings.Len(Me.m_EmailAddress) - iAtSign
        Dim sDomain As String = Microsoft.VisualBasic.Strings.Right(Me.m_EmailAddress, iDomainLength)
        Dim bResolvable As Boolean = False
        Try
            Dim ip As System.Net.IPHostEntry = System.Net.Dns.GetHostEntry(sDomain)
            bResolvable = True
        Catch ex As Exception
            Throw New Exception(Me.m_EmailAddress & " is not from a resolvable domain.")
        End Try
        Return bResolvable
    End Function

    ' save the value to the database
    Public Sub Write(w As System.IO.BinaryWriter) Implements IBinarySerialize.Write
        w.Write(Me.m_EmailAddress)
    End Sub

    ' retrieve the value from the database
    Public Sub Read(r As System.IO.BinaryReader) Implements IBinarySerialize.Read
        Dim sTemp As String = r.ReadString
        Dim sTemp1 As String = ""
        For Each n As Char In sTemp.ToCharArray
            sTemp1 = sTemp1 & n.ToString
        Next
        Me.m_EmailAddress = sTemp
    End Sub

End Structure

上記のコードは署名されていないため、TRUSTWORTHYデータベース設定を有効にできる開発マシンでのみテストする必要があります。コードをコンパイルしたら、次の方法でSQL Serverにインポートします。

CREATE Assembly SQLCLREmailType 
AUTHORIZATION dbo 
FROM 'C:\Path\Goes\Here\SQLCLREmailType.dll' 
WITH PERMISSION_SET = UNSAFE;

CREATE TYPE EmailType
EXTERNAL NAME SQLCLREmailType.[SQLCLREmailType.EmailType]

UDTは次のように使用できます。

DECLARE @t TABLE (
    col EmailType NOT NULL
    );

INSERT INTO @t (col)
VALUES ('[email protected]')
    , ('[email protected]');

SELECT CONVERT(varchar(50), t.col)
FROM @t t
GO

上記のコードは次を返します:

+ ------------------ + 
 | (列名なし)| 
 + ------------------ + 
 | [email protected] | 
 | [email protected] | 
 + ------------------ +

ただし、次のように、存在しないメールドメインに属するアドレスを挿入しようとすると、

DECLARE @t TABLE (
    col EmailType NOT NULL
    );

INSERT INTO @t (col)
VALUES , ('us@asdfasdfasdfasdfasdfasdfasdfasdf90097809878907098908908908908.com');

SELECT CONVERT(varchar(50), t.col)
FROM @t t
GO

エラーが表示されます:

メッセージ6522、レベル16、状態2、行27
ユーザー定義ルーチンまたは集計「EmailType」の実行中に.NET Frameworkエラーが発生しました:
System.Exception:us@asdfasdfasdfasdfasdfasdfasdfasdf90097809878907098908908908908.com is not from a resolvable domain。
System.Exception:
at SQLCLREmailType.EmailType.IsValidDomain()
at SQLCLREmailType.EmailType.ValidateEmailAddress()
at SQLCLREmailType.EmailType.Parse(SqlString s)

10
Max Vernon

may回避策があるため、これを選択済みとしてマークするつもりはありませんが、技術的にはサポートされていません。あなたは問題を見ることができます Microsoft Connect上で

こんにちはアーランド、

パイプライン内のすべての提案項目を注意深く評価した後、現在優先度の高い項目のために近い将来実装されない項目をクローズします。クローズされた提案は、今後、製品ロードマップに基づいて再評価します。

製品の提案と製品の継続的なサポートを提供していただき、ありがとうございます。

-SQLプログラマビリティチームUmachandar

この問題は2012年に公開されました。

3
Evan Carroll