SQL Server có hỗ trợ DOMAIN tùy chỉnh không?


8

PostgreSQL hỗ trợ DOMAINđặc tả kỹ thuật , từ thông số dự thảo hoạt động SQL 2011,

Tên miền là một đối tượng do người dùng định nghĩa có thể được chỉ định thay thế cho loại dữ liệu ở một số nơi nhất định có thể chỉ định loại dữ liệu. Một miền bao gồm một loại dữ liệu, có thể là một tùy chọn mặc định và các ràng buộc bằng không hoặc nhiều hơn (miền).

Điều này cho phép chúng tôi thực hiện những thứ thực sự tuyệt vời như triển khai một tên miền cho HTML5-spec cho email qua một loại văn bản không phân biệt chữ hoa chữ thường . Nó đảm bảo rằng tất cả các máy khách truy cập cơ sở dữ liệu đều có kiểm tra tính toàn vẹn trên dữ liệu được chèn.

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 có hỗ trợ bất kỳ chức năng nào như vậy bên ngoài hệ thống kích hoạt không?


1
Điều gần nhất là các quy tắc nhưng chúng không được chấp nhận
a_horse_with_no_name

Câu trả lời:


10

SQLCLR trình bày một diện tích bề mặt để tạo các kiểu dữ liệu hoàn toàn tùy chỉnh. Trong thực tế, đó là cách SQL Server hỗ trợ các kiểu dữ liệu hình học và phân cấp.

Do SQLCLR dựa trên ngôn ngữ trung gian phổ biến Microsoft.Net, nên có nhiều ràng buộc lớn đối với kiểu dữ liệu SQLCLR. Chẳng hạn, bạn có thể dễ dàng đảm bảo địa chỉ email đến từ một miền hợp lệ bằng cách truy vấn DNS cho bản ghi MX như một phần của mã xác thực dữ liệu.

SQL Server có thể lập chỉ mục UDR CLT miễn là IsByteOrdered:=Trueđược đặt. Có rất nhiều thuộc tính như thế, mà bạn có thể thay đổi để ảnh hưởng đến cách SQL Server sử dụng UDT. Để khớp bằng như yêu cầu của một chỉ mục, SQL Server chỉ cần xem giá trị nhị phân được lưu trữ trong trang tức là không cần phải xem mã UDT.

Như một ví dụ về loại SQLCLR do người dùng định nghĩa kiểm tra tính hợp lệ của không gian miền, tôi đã viết mã VB.Net bằng chứng khủng khiếp về khái niệm sau:

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

Vì mã ở trên chưa được ký, bạn chỉ nên kiểm tra mã trên máy phát triển nơi bạn có thể bật TRUSTWORTHYcài đặt cơ sở dữ liệu. Sau khi mã được biên dịch, bạn nhập mã vào SQL Server thông qua các bước sau:

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 sau đó có thể được sử dụng như thế này:

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

Mã trên trả về:

+ ------------------ +
| (Không có tên cột) |
+ ------------------ +
| mvernon@mvct.com |
| us@them.com |
+ ------------------ +

Tuy nhiên, khi cố gắng chèn một địa chỉ thuộc về một tên miền email không tồn tại, như trong:

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

Bạn thấy một lỗi:

Msg 6522, Cấp 16, Trạng thái 2, Dòng 27 Đã
xảy ra lỗi .NET Framework trong khi thực hiện quy trình do người dùng xác định hoặc tổng hợp "EmailType":
System.Exception: us@asdfasdfasdfasdfasdfasdfasdfasdf90097809878907098908908908908.com không phải là từ một miền.
System.Exception:
tại SQLCLREmailType.EmailType.IsValidDomain ()
tại SQLCLREmailType.EmailType.ValidateEmailAddress ()
tại SQLCLREmailType.EmailType.Pude (SqlString s)


1
truy vấn DNS cho bản ghi MX sẽ tốt hơn nhiều khi được thực hiện bên ngoài SQL Server.
Martin Smith

@MartinSmith - chắc chắn nhất; Tôi sẽ không bao giờ thực sự làm theo cách này trong thực tế. Đây chỉ là một bằng chứng về khái niệm.
Max Vernon

3

Tôi sẽ không đánh dấu điều này là đã chọn vì có thể có một công việc xung quanh, nhưng về mặt kỹ thuật chúng không được hỗ trợ. Bạn có thể thấy vấn đề trên Microsoft Connect.

Xin chào Erland,

Sau khi đánh giá cẩn thận tất cả các mục đề xuất trong đường ống của chúng tôi, chúng tôi sẽ đóng các mục mà chúng tôi sẽ không triển khai trong tương lai gần do các mục ưu tiên cao hơn hiện tại. Chúng tôi sẽ đánh giá lại các đề xuất đã đóng một lần nữa trong tương lai dựa trên lộ trình sản phẩm.

Cảm ơn một lần nữa vì đã cung cấp gợi ý sản phẩm và tiếp tục hỗ trợ cho sản phẩm của chúng tôi.

- Umachandar, Nhóm lập trình SQL

Vấn đề đã được mở vào năm 2012.


Mục Kết nối được tham chiếu cho biết Microsoft sẽ không triển khai CREATE DOMAINtrong phiên bản hiện tại của SQL Server (2012). Nó không có nghĩa là các tính năng không được hỗ trợ, như thể hiện bởi câu trả lời của tôi.
Max Vernon ngày
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.