SQLCLR bietet eine Oberfläche zum Erstellen vollständig benutzerdefinierter Datentypen. Auf diese Weise unterstützt SQL Server geometrische Datentypen und Hierarchiedatentypen.
Da SQLCLR auf der Common-Intermediate-Sprache von Microsoft.Net basiert, sind für einen SQLCLR-Datentyp eine Vielzahl von Einschränkungen möglich. Sie können beispielsweise leicht sicherstellen, dass eine E-Mail-Adresse von einer gültigen Domain stammt, indem Sie DNS als Teil des Datenüberprüfungscodes nach dem MX-Eintrag abfragen.
SQL Server kann eine CLR-UDT indizieren, solange sie festgelegt IsByteOrdered:=True
ist. Es gibt eine Menge solcher Eigenschaften, die Sie ändern können, um die Verwendung von UDT durch SQL Server zu beeinflussen. Für eine Gleichheitsübereinstimmung, wie sie für einen Index erforderlich ist, überprüft SQL Server einfach den auf der Seite gespeicherten Binärwert, dh er muss den UDT-Code überhaupt nicht anzeigen.
Als Beispiel für einen benutzerdefinierten SQLCLR-Typ, der einen Domänenbereich auf Gültigkeit überprüft, habe ich den folgenden schrecklichen Proof-of-Concept-VB.Net-Code geschrieben:
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
Da der obige Code nicht signiert ist, sollten Sie ihn nur auf einem Entwicklungscomputer testen, auf dem Sie die TRUSTWORTHY
Datenbankeinstellung aktivieren können . Sobald der Code kompiliert ist, importieren Sie ihn wie folgt in 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]
Das UDT kann dann folgendermaßen verwendet werden:
DECLARE @t TABLE (
col EmailType NOT NULL
);
INSERT INTO @t (col)
VALUES ('mvernon@mvct.com')
, ('us@them.com');
SELECT CONVERT(varchar(50), t.col)
FROM @t t
GO
Der obige Code gibt Folgendes zurück:
+ ------------------ +
| (Kein Spaltenname) |
+ ------------------ +
| mvernon@mvct.com |
| us@them.com |
+ ------------------ +
Wenn Sie jedoch versuchen, eine Adresse einzufügen, die zu einer nicht vorhandenen E-Mail-Domäne gehört, wie in:
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
Sie sehen einen Fehler:
Meldung 6522, Ebene 16,
Status 2, Zeile 27 Während der Ausführung der benutzerdefinierten Routine oder des Aggregats "EmailType" ist ein .NET Framework-Fehler aufgetreten:
System.Exception: us@asdfasdfasdfasdfasdfasdfasdfasdf90097809878907098908908908908.com stammt nicht aus einer auflösbaren Domäne.
System.Exception:
bei SQLCLREmailType.EmailType.IsValidDomain ()
bei SQLCLREmailType.EmailType.ValidateEmailAddress ()
bei SQLCLREmailType.EmailType.Parse (SqlString s)