Udostępnij za pośrednictwem


Kodowanie Typy definiowane przez użytkownika

Podczas kodowania definition typ zdefiniowany przez użytkownika (UDT), należy zaimplementować różnych funkcji, w zależności od tego, czy użytkownik są wykonania UDT jako klasy lub struktury, jak również opcje formatu i szeregowania został wybrany.

W przykładzie w tej sekcji przedstawiono wykonywania Point UDT jako struct (lub Structure w języku Visual Basic). The Point UDT consists of X and Y coordinates implemented as właściwość procedures.

Podczas definiowania UDT wymagane są następujące obszary nazw:

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

The Microsoft.SqlServer.Server namespace contains the objects required for various attributes of your UDT, and the System.Data.SqlTypes namespace contains the classes that represent SQL Server native data types available to the wirtualny plik dziennika. Oczywiście mogą istnieć dodatkowe obszary nazw, które z wirtualny plik dziennika wymaga do poprawnego działania.The Point UDT also uses the System.Text namespace for working with strings.

Uwaga

Zaczyna się od SQL Server 2005Wizualne obiekty bazy danych języka C++, takie jak UDTs skompilowany z /clr:pure nie są obsługiwane na wykonanie.

Określanie atrybutów

Atrybuty określają, jak serializacji jest używana do konstruowania reprezentacja magazynowania UDTs i przekazywanie UDTs przez wartość do klient.

The Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute is required.The Serializable atrybut is optional. Można również określić Microsoft.SqlServer.Server.SqlFacetAttribute Aby znaleźć informacje na temat zwracany typ UDT. Aby uzyskać więcej informacji zobaczNiestandardowe atrybuty dla środowiska CLR procedur.

Atrybuty punktu UDT

The Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute sets the storage format for the Point UDT to Native.IsByteOrdered is set to true, which guarantees that the results of comparisons are the same in SQL Server as if the same comparison had taken place in managed code.Implementuje UDT System.Data.SqlTypes.INullable Interfejs służący do uświadomić UDT null.

Poniższy fragment kodu zawiera atrybuty dla Point UDT.

<Serializable(), SqlUserDefinedTypeAttribute(Format.Native, _
  IsByteOrdered:=True)> _
  Public Structure Point
    Implements INullable
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.Native,
  IsByteOrdered=true)]
public struct Point : INullable
{

Wykonania opcje dopuszczania wartości null

Oprócz określenia atrybutów z zestawów poprawnie, Twój UDT musi obsługiwać opcje dopuszczania wartości null.UDTs ładowane do SQL Server wartość zerowa obsługują, ale aby UDT rozpoznawał wartości null, musi implementować UDT System.Data.SqlTypes.INullable interfejs.

Należy utworzyć właściwość o nazwie IsNull, który jest potrzebny do ustalenia, czy wartość jest null z kodem środowiska CLR. Kiedy SQL Server Wyszukuje wartości null wystąpienie UDT, the UDT jest zachowywane przy użyciu normalnych metod obsługi null. Serwer nie odpadów czas serializacji lub deserializacji UDT, jeśli nie ma, a nie on odpadów miejsca do przechowywania wartości null UDT.Ten test dla wartości null jest wykonywane przy każdym UDT jest umieszczany od środowiska CLR, co oznacza, że przy użyciu Transact-SQL IS NULL skonstruować Sprawdź, czy zerowe UDTs zawsze powinny działać. The IsNull właściwość is also used by the server to test whether an wystąpienie is null. Gdy serwer określa, że UDT ma wartość null, może używać jego macierzystej obsługi wartości null.

The get() metoda of IsNull is not special-cased in any way. Jeśli Point Zmienna @p jest Null, następnie @p.IsNullDomyślnie oceni "Null", nie "1". Dzieje się tak, ponieważ SqlMethod(OnNullCall) atrybut IsNull get() Metoda wartością domyślną jest FALSE. Ponieważ obiekt jest Null, gdy wymagana jest właściwość obiektu nie jest rozszeregować, nie jest wywoływana metoda i zwracana jest wartość domyślna "NULL".

Przykład

W poniższym przykładzie is_Null Zmienna jest oznaczony jako prywatny i ma stan o wartości null dla wystąpienie UDT. Kod musi zachować odpowiednią wartość dla is_Null. UDT musi także mieć właściwość statycznej o nazwie Null które zwraca wartość null wystąpienie UDT. Dzięki temu UDT ma zostać zwrócona wartość null, jeśli instancja jest w rzeczywistości null w bazie danych.

Private is_Null As Boolean

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 New Point
        pt.is_Null = True
        Return (pt)
    End Get
End Property
private bool is_Null;

public bool IsNull
{
    get
    {
        return (is_Null);
    }
}

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

IS NULL w stosunku do.IsNull

Należy wziąć pod uwagę tabela, która zawiera punkty schematu (identyfikator int, punkt lokalizacji), gdzie Point jest UDT środowiska CLR i następujące kwerendy:

--Query 1
SELECT ID
FROM Points
WHERE NOT (location IS NULL) -- Or, WHERE location IS NOT NULL

--Query 2:
SELECT ID
FROM Points
WHERE location.IsNull = 0

Zarówno kwerendy zwracają identyfikatory punktów o innych niż-Null lokalizacje. 1 Query normalnej obsługi null jest używany, a nie deserializacji UDTs jest wymagane.Kwerenda 2, z drugiej strony, ma deserializować każdego nie-Null obiekt, a następnie wywołać ją do środowiska CLR w celu uzyskania wartości IsNull Właściwość. Wyraźnie przy użyciu IS NULL będzie może zawierać większą wydajność i nigdy nie należy z powodu odczytać IsNull Właściwość UDT z Transact-SQL Kod.

W ten sposób, co to jest użycie IsNull Właściwość?Po pierwsze jest potrzebne do ustalenia, czy wartość jest Null w ramach środowiska CLR code. Po drugie serwer wymaga, aby sprawdzić, czy jest wystąpienie Null, aby ta właściwość jest używana przez serwer. Po ustali, że jest on Null, a następnie jego macierzystej obsługi null mogą być używane do jego obsługi.

Metoda analizy wykonania

The Parse and ToString methods allow for conversions to and from ciąg representations of the UDT. The Parse metoda allows a ciąg to be converted into a UDT. To musi być zadeklarowany jako static (lub Shared w języku Visual Basic) oraz parametr typu System.Data.SqlTypes.SqlString.

Następujący kod implementuje Parse Metoda Point UDT, która oddziela się współrzędne X i Y. The Parse metoda has a single argument of type System.Data.SqlTypes.SqlString, and assumes that X and Y values are supplied as a comma-delimited ciąg. Ustawianie Microsoft.SqlServer.Server.SqlMethodAttribute.OnNullCall atrybut do false Zapobiega Parse Metoda od wywoływanej z punktu wystąpienie wartości null.

<SqlMethod(OnNullCall:=False)> _
Public Shared Function Parse(ByVal s As SqlString) As Point
    If s.IsNull Then
        Return Null
    End If

    ' Parse input string here to separate out points.
    Dim pt As New Point()
    Dim xy() As String = s.Value.Split(",".ToCharArray())
    pt.X = Int32.Parse(xy(0))
    pt.Y = Int32.Parse(xy(1))
    Return pt
End Function
[SqlMethod(OnNullCall = false)]
public static Point Parse(SqlString s)
{
    if (s.IsNull)
        return Null;

    // Parse input string to separate out points.
    Point pt = new Point();
    string[] xy = s.Value.Split(",".ToCharArray());
    pt.X = Int32.Parse(xy[0]);
    pt.Y = Int32.Parse(xy[1]);
    return pt;
}

Metoda ToString wykonania

The ToString metoda converts the Point UDT to a ciąg value. przypadek wystąpienie wartości null zostanie zwrócony ciąg "NULL" Point Typ. The ToString metoda reverses the Parse metoda by using a System.Text.StringBuilder to return a comma-delimited System.String consisting of the X and Y coordinate values. Ponieważ InvokeIfReceiverIsNull wartością domyślną jest false, wyboru dla wystąpienie wartości null Point nie jest konieczne.

Private _x As Int32
Private _y As Int32

Public Overrides Function ToString() As String
    If Me.IsNull Then
        Return "NULL"
    Else
        Dim builder As StringBuilder = New StringBuilder
        builder.Append(_x)
        builder.Append(",")
        builder.Append(_y)
        Return builder.ToString
    End If
End Function
private Int32 _x;
private Int32 _y;

public override string ToString()
{
    if (this.IsNull)
        return "NULL";
    else
    {
        StringBuilder builder = new StringBuilder();
        builder.Append(_x);
        builder.Append(",");
        builder.Append(_y);
        return builder.ToString();
    }
}

Narażania UDT właściwości

The Point UDT exposes X and Y coordinates that are implemented as public read-write properties of type System.Int32.

Public Property X() As Int32
    Get
        Return (Me._x)
    End Get

    Set(ByVal Value As Int32)
        _x = Value
    End Set
End Property

Public Property Y() As Int32
    Get
        Return (Me._y)
    End Get

    Set(ByVal Value As Int32)
        _y = Value
    End Set
End Property
public Int32 X
{
    get
    {
        return this._x;
    }
    set 
    {
        _x = value;
    }
}

public Int32 Y
{
    get
    {
        return this._y;
    }
    set
    {
        _y = value;
    }
}

Sprawdzanie poprawności wartości UDT

Podczas pracy z danymi UDT SQL Server Database Engine automatycznie konwertuje wartości binarnych na wartości UDT. Ten proces konwersji polega na sprawdzenie, czy wartości są odpowiednie dla format serializacji tego typu oraz zapewnienia, że wartość może być poprawnie rozszeregować.Pozwala to uzyskać pewność, że wartości mogą być konwertowane do postaci binarnej.W stosunku do zamówionej bajt UDTs to także zapewnia zgodność wynikową wartość binarna oryginalna wartość binarna.Dzięki temu nieprawidłowe wartości są utrwalane w bazie danych.W niektórych przypadkach ten poziom sprawdzania może być niewystarczająca.Dodatkowe sprawdzenie poprawności może być wymagane w przypadku musi być domena oczekiwanego lub zakres wartości UDT.Na przykład UDT, implementującą data może wymagać wartości dnia jest liczbą dodatnią, która znajduje się w pewnym zakresie prawidłowych wartości.

The Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.ValidationMethodName property of the Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute allows you to supply the name of a validation method that the server runs when data is assigned to a UDT or converted to a UDT.ValidationMethodName is also called during the running of the bcp utility, BULK INSERT, DBCC CHECKDB, DBCC CHECKFILEGROUP, DBCC CHECKTABLE, distributed query, and tabular data stream (TDS) remote procedure call (RPC) operations.Wartość domyślna ValidationMethodName ma wartość null wskazującą, że nie ma metoda sprawdzania poprawności.

Przykład

Poniższy fragment kodu zawiera deklaracja Point klasy, która określa ValidationMethodName z ValidatePoint.

<Serializable(), SqlUserDefinedTypeAttribute(Format.Native, _
  IsByteOrdered:=True, _
  ValidationMethodName:="ValidatePoint")> _
  Public Structure Point
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.Native,
  IsByteOrdered=true, 
  ValidationMethodName = "ValidatePoint")]
public struct Point : INullable
{

Metoda sprawdzania poprawności jest określony, musi on mieć podpis, który przypomina następujący fragment kodu.

Private Function ValidationFunction() As Boolean
    If (validation logic here) Then
        Return True
    Else
        Return False
    End If
End Function
private bool ValidationFunction()
{
    if (validation logic here)
    {
        return true;
    }
    else
    {
        return false;
    }
}

Metoda sprawdzania poprawności może być każdy zakres i powinien zwrócić true Jeśli wartość jest prawidłowa, a false w przeciwnym razie. Jeśli metoda zwraca false lub generuje wyjątek, wartość jest traktowany jako wywoływane jest nieprawidłowy i błąd.

W poniższym przykładzie kodu umożliwia tylko wartości zero lub większa współrzędne X i Y.

Private Function ValidatePoint() As Boolean
    If (_x >= 0) And (_y >= 0) Then
        Return True
    Else
        Return False
    End If
End Function
private bool ValidatePoint()
{
    if ((_x >= 0) && (_y >= 0))
    {
        return true;
    }
    else
    {
        return false;
    }
}

Ograniczenia metoda sprawdzania poprawności

Serwer wywołuje metoda sprawdzania poprawności, gdy serwer wykonuje konwersje, nie, po wstawieniu danych przez ustawienie właściwości poszczególnych lub po wstawieniu danych przy użyciu Transact-SQL INSERT instrukcja.

Metoda sprawdzania poprawności musi jawnie wywołać z ustawiających właociwooci oraz Analizowanie metody, jeśli chcesz, aby metoda sprawdzania poprawności używana we wszystkich sytuacjach.Nie jest to wymagane, a w niektórych przypadkach może nie nawet być pożądane.

Analizowanie przykład sprawdzania poprawności

Aby upewnić się, że ValidatePoint metoda jest wywoływana w Punkt klasy, należy go wywołać z Analizowanie metody oraz od procedury właściwość, zestaw X i Y koordynować wartości.Poniższy fragment kodu pokazuje, jak wywołać ValidatePoint Metoda z Analizowanie funkcja.

<SqlMethod(OnNullCall:=False)> _
Public Shared Function Parse(ByVal s As SqlString) As Point
    If s.IsNull Then
        Return Null
    End If

    ' Parse input string here to separate out points.
    Dim pt As New Point()
    Dim xy() As String = s.Value.Split(",".ToCharArray())
    pt.X = Int32.Parse(xy(0))
    pt.Y = Int32.Parse(xy(1))

    ' Call ValidatePoint to enforce validation
    ' for string conversions.
    If Not pt.ValidatePoint() Then
        Throw New ArgumentException("Invalid XY coordinate values.")
    End If
    Return pt
End Function
[SqlMethod(OnNullCall = false)]
public static Point Parse(SqlString s)
{
    if (s.IsNull)
        return Null;

    // Parse input string to separate out points.
    Point pt = new Point();
    string[] xy = s.Value.Split(",".ToCharArray());
    pt.X = Int32.Parse(xy[0]);
    pt.Y = Int32.Parse(xy[1]);

    // Call ValidatePoint to enforce validation
    // for string conversions.
    if (!pt.ValidatePoint()) 
        throw new ArgumentException("Invalid XY coordinate values.");
    return pt;
}

Właściwość przykład sprawdzania poprawności

Poniższy fragment kodu pokazuje, jak wywołać ValidatePoint metoda sprawdzania poprawności z procedur właściwość, które współrzędne X i Y.

Public Property X() As Int32
    Get
        Return (Me._x)
    End Get

    Set(ByVal Value As Int32)
        Dim temp As Int32 = _x
        _x = Value
        If Not ValidatePoint() Then
            _x = temp
            Throw New ArgumentException("Invalid X coordinate value.")
        End If
    End Set
End Property

Public Property Y() As Int32
    Get
        Return (Me._y)
    End Get

    Set(ByVal Value As Int32)
        Dim temp As Int32 = _y
        _y = Value
        If Not ValidatePoint() Then
            _y = temp
            Throw New ArgumentException("Invalid Y coordinate value.")
        End If
    End Set
End Property
    public Int32 X
{
    get
    {
        return this._x;
    }
    // Call ValidatePoint to ensure valid range of Point values.
    set 
    {
        Int32 temp = _x;
        _x = value;
        if (!ValidatePoint())
        {
            _x = temp;
            throw new ArgumentException("Invalid X coordinate value.");
        }
    }
}

public Int32 Y
{
    get
    {
        return this._y;
    }
    set
    {
        Int32 temp = _y;
        _y = value;
        if (!ValidatePoint())
        {
            _y = temp;
            throw new ArgumentException("Invalid Y coordinate value.");
        }
    }
}

Metody kodowania UDT

Kodowanie UDT metody, należy rozważyć, czy użytego algorytmu prawdopodobnie można zmieniać w czasie.W takim przypadku warto rozważyć tworzenie oddzielnych klasy dla metod UDT sieci korzysta.Jeśli algorytm ulegnie zmianie, można ponownie skompilować klasy z nowym kodem i załadować wirtualny plik dziennika do SQL Server nie ma wpływu na UDT. W wielu przypadkach UDTs mogą być ładowane przy użyciu Transact-SQL ALTER wirtualny plik dziennika instrukcji, lecz potencjalnie mogą powodować problemy z istniejących danych. Na przykład Waluta Dołączone UDTAdventureWorks korzysta z przykładowej bazy danych ConvertCurrency funkcja konwersji walut, który zaimplementowano w osobnej klasy.Istnieje możliwość konwersji algorytmy mogą ulec zmianie w sposób nieprzewidywalny w przyszłości lub Nowa funkcja może być wymagane.Oddzielanie ConvertCurrency funkcjaWaluta Implementacja UDT zapewnia większą elastyczność przy planowaniu przyszłych zmian.

Aby uzyskać informacje dotyczące sposobu instalowania AdventureWorks Środowisko CLR próbek, zobacz "Instalowanie przykłady" w SQL Server Książki online.

Przykład

The Point class contains three simple methods for calculating distance: Odległość, DistanceFrom and DistanceFromXY.Każdy zwraca double Obliczanie odległości od Point na zero, odległość od określonego punktu na Point, a odległość od określonych współrzędnych X i Y do Point. Odległość and DistanceFrom każdego wywołania DistanceFromXY, a przedstawienie sposobu używania różnych argumentów dla każdej metoda.

' Distance from 0 to Point.
<SqlMethod(OnNullCall:=False)> _
Public Function Distance() As Double
    Return DistanceFromXY(0, 0)
End Function

' Distance from Point to the specified point.
<SqlMethod(OnNullCall:=False)> _
Public Function DistanceFrom(ByVal pFrom As Point) As Double
    Return DistanceFromXY(pFrom.X, pFrom.Y)
End Function

' Distance from Point to the specified x and y values.
<SqlMethod(OnNullCall:=False)> _
Public Function DistanceFromXY(ByVal ix As Int32, ByVal iy As Int32) _
    As Double
    Return Math.Sqrt(Math.Pow(ix - _x, 2.0) + Math.Pow(iy - _y, 2.0))
End Function
// Distance from 0 to Point.
[SqlMethod(OnNullCall = false)]
public Double Distance()
{
    return DistanceFromXY(0, 0);
}

// Distance from Point to the specified point.
[SqlMethod(OnNullCall = false)]
public Double DistanceFrom(Point pFrom)
{
    return DistanceFromXY(pFrom.X, pFrom.Y);
}

// Distance from Point to the specified x and y values.
[SqlMethod(OnNullCall = false)]
public Double DistanceFromXY(Int32 iX, Int32 iY)
{
    return Math.Sqrt(Math.Pow(iX - _x, 2.0) + Math.Pow(iY - _y, 2.0));
}

Za pomocą atrybutów SqlMethod

The Microsoft.SqlServer.Server.SqlMethodAttribute class provides custom attributes that can be used to mark metoda definitions in order to specify determinism, on null call behavior, and to specify whether a metoda is a mutator. Zakłada się, że domyślne wartości tych właściwości, a atrybut niestandardowy jest używane tylko wtedy, gdy wartość domyślna nie jest potrzebny.

Uwaga

The SqlMethodAttribute class inherits from the SqlFunctionAttribute class, so SqlMethodAttribute inherits the FillRowMethodName and TableDefinition fields from SqlFunctionAttribute.Oznacza to, że jest możliwe jest tworzenie metoda wycenione tabela, która nie jest dostępna.Metoda kompiluje i zespołu wdraża, ale błąd o IEnumerable typ zwracany jest uruchamiany w czasie wykonywania z następującym komunikatem: "Metoda, właściwość lub pole"Nieprawidłowy typ zwrotny ma nazwę < > "w klasie < klasa > w zestawie "wirtualny plik dziennika < >"."

W poniższej tabela przedstawiono niektóre z odpowiednią Microsoft.SqlServer.Server.SqlMethodAttribute właściwości, które mogą być używane w metodach UDT i wyświetla wartości domyślnych.

  • DataAccess
    Wskazuje, czy funkcja wymaga dostępu do danych użytkownika, przechowywane w lokalnym wystąpienie SQL Server. Wartością domyślną jest DataAccessKind. None.

  • IsDeterministic
    Wskazuje, czy funkcja daje taki sam, dane wyjściowe podanych na tej samej wartości wejściowych i tym samym stanie bazy danych.Wartością domyślną jest false.

  • IsMutator
    Wskazuje, czy metoda powoduje zmianę stanu w wystąpieniu UDT.Wartością domyślną jest false.

  • IsPrecise
    Wskazuje, czy funkcja pociąga za sobą nieprecyzyjne obliczeń, takich jak ruchomy operacji.Wartością domyślną jest false.

  • OnNullCall
    Wskazuje, czy metoda jest wywoływane, gdy określone argumenty wejściowe odwołania zerowego.Wartością domyślną jest true.

Przykład

The Microsoft.SqlServer.Server.SqlMethodAttribute.IsMutator property allows you to mark a method that allows a change in the state of an instance of a UDT.Transact-SQL does not allow you to set two UDT properties in the SET clause of one UPDATE statement.Jednak może mieć formę oznaczony jako mutator, który zmienia się dwa elementy.

Uwaga

Metody mutator nie są dozwolone w kwerendach.Te mogą być wywoływane tylko w instrukcji przypisania lub instrukcji modyfikacji danych.Jeśli metoda oznaczona jako mutator nie zwraca void (lub nie jest Sub w języku Visual Basic) CREATE TYPE nie powiedzie się z powodu błędu.

Poniższa instrukcja zakłada się istnienie Triangles UDT, który ma Rotate Metoda. Poniżej Transact-SQL wywołuje instrukcję aktualizującą Rotate Metoda:

UPDATE Triangles SET t.RotateY(0.6) WHERE id=5

The Rotate metoda is decorated with the SqlMethod atrybut setting IsMutator to true so that SQL Server can mark the metoda as a mutator metoda. Ustawia również kod OnNullCall Aby false, która wskazuje na serwer, metoda zwraca wartość (odwołania zerowegoNothing w języku Visual Basic) czy parametry wejściowe są odwołania do wartości null.

<SqlMethod(IsMutator:=True, OnNullCall:=False)> _
Public Sub Rotate(ByVal anglex as Double, _
  ByVal angley as Double, ByVal anglez As Double) 
   RotateX(anglex)
   RotateY(angley)
   RotateZ(anglez)
End Sub
[SqlMethod(IsMutator = true, OnNullCall = false)]
public void Rotate(double anglex, double angley, double anglez) 
{
   RotateX(anglex);
   RotateY(angley);
   RotateZ(anglez);
}

Wykonania UDT za pomocą formatu zdefiniowanego przez użytkownika

Podczas implementowania UDT w formacie zdefiniowane przez użytkownika, należy zaimplementować Read i Write metody, które implementują interfejs Microsoft.SqlServer.Server.IBinarySerialize do szeregowania i podczas deserializacji danych UDT. Należy także określić MaxByteSize Właściwość Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute.

Waluta UDT

The Currency UDT is included with the CLR samples that can be installed with SQL Server, beginning with SQL Server 2005.Aby uzyskać informacje dotyczące sposobu instalowania próbek CLR zobacz Considerations for Installing SQL Server Samples and Sample Databases.

The Currency UDT supports handling amounts of money in the monetary system of a particular culture.Należy zdefiniować dwa pola: a string dla CultureInfo, określa, którzy wydane w walucie (en-us, na przykład) i decimal dla CurrencyValue, ilość pieniędzy.

Chociaż nie jest on używany przez serwer do przeprowadzania porównań, Currency Implementuje UDT System.IComparable interfejs, który udostępnia jedną metoda, System.IComparable.CompareTo. Używany w sytuacjach, gdy pożądane jest, aby dokładnie porównania lub kolejność wartości waluty w ramach kultur po stronie klient.

Kod wykonywany w środowisko CLR porównuje kultury niezależnie od wartości waluty.Dla Transact-SQL kod, następujące akcje określają porównania:

  1. Ustawianie IsByteOrdered atrybut na wartość true, która informuje o tym SQL Server Aby użyć utrwalonej reprezentacja binarna na dysku dla porównania.

  2. Użycie Write Metoda Currency UDT do określenia, w jaki sposób UDT jest zachowywane na dysku, i w związku z tym jak UDT wartości są porównywane i zamówionych dla Transact-SQL operacje.

  3. Zapisz Currency W następującym formacie binarnym UDT:

    1. Zapisz kultury jako ciąg kodowania UTF-16 bajtów 0-19 z uzupełnienie prawej strony tego pola ze znakami null.

    2. Za pomocą 20 bajtów i powyżej, aby zawierać wartości dziesiętne waluty.

Celem uzupełnienie jest zapewniające kultury jest całkowicie oddzielony od wartości waluty, dzięki czemu po jednym UDT jest porównywany Transact-SQL kodem bajtów są porównywane bajtów kultury Kultura i wartościami bajtów waluty są porównywane wartości bajtu waluty.

Zakończenie kodu dla Currency UDT, postępuj zgodnie z instrukcjami instalowania środowiska CLR próbki w Considerations for Installing SQL Server Samples and Sample Databases.

Atrybuty waluty

The Currency UDT is defined with the following attributes.

<Serializable(), Microsoft.SqlServer.Server.SqlUserDefinedType( _
    Microsoft.SqlServer.Server.Format.UserDefined, _
    IsByteOrdered:=True, MaxByteSize:=32), _
    CLSCompliant(False)> _
Public Structure Currency
Implements INullable, IComparable, _
Microsoft.SqlServer.Server.IBinarySerialize
[Serializable]
[SqlUserDefinedType(Format.UserDefined, 
    IsByteOrdered = true, MaxByteSize = 32)]
    [CLSCompliant(false)]
    public struct Currency : INullable, IComparable, IBinarySerialize
    {

Tworzenie, Odczyt i zapis metody z IBinarySerialize

Po wybraniu UserDefined format serializacji, należy także zaimplementować IBinarySerialize interfejs i tworzyć swoje własne Read i Write metody. Następujące procedury od Currency Użycie UDT System.IO.BinaryReader i System.IO.BinaryWriter Aby odczytywać i zapisywać UDT.

' IBinarySerialize methods
' The binary layout is as follow:
'    Bytes 0 - 19: Culture name, padded to the right with null
'    characters, UTF-16 encoded
'    Bytes 20+: Decimal value of money
' If the culture name is empty, the currency is null.
Public Sub Write(ByVal w As System.IO.BinaryWriter) _
  Implements Microsoft.SqlServer.Server.IBinarySerialize.Write
    If Me.IsNull Then
        w.Write(nullMarker)
        w.Write(System.Convert.ToDecimal(0))
        Return
    End If

    If cultureName.Length > cultureNameMaxSize Then
        Throw New ApplicationException(String.Format(CultureInfo.CurrentUICulture, _
           "{0} is an invalid culture name for currency as it is too long.", cultureNameMaxSize))
    End If

    Dim paddedName As String = cultureName.PadRight(cultureNameMaxSize, CChar(vbNullChar))

    For i As Integer = 0 To cultureNameMaxSize - 1
        w.Write(paddedName(i))
    Next i

    ' Normalize decimal value to two places
    currencyVal = Decimal.Floor(currencyVal * 100) / 100
    w.Write(currencyVal)
End Sub

Public Sub Read(ByVal r As System.IO.BinaryReader) _
  Implements Microsoft.SqlServer.Server.IBinarySerialize.Read
    Dim name As Char() = r.ReadChars(cultureNameMaxSize)
    Dim stringEnd As Integer = Array.IndexOf(name, CChar(vbNullChar))

    If stringEnd = 0 Then
        cultureName = Nothing
        Return
    End If

    cultureName = New String(name, 0, stringEnd)
    currencyVal = r.ReadDecimal()
End Sub
// IBinarySerialize methods
// The binary layout is as follow:
//    Bytes 0 - 19:Culture name, padded to the right 
//    with null characters, UTF-16 encoded
//    Bytes 20+:Decimal value of money
// If the culture name is empty, the currency is null.
public void Write(System.IO.BinaryWriter w)
{
    if (this.IsNull)
    {
        w.Write(nullMarker);
        w.Write((decimal)0);
        return;
    }

    if (cultureName.Length > cultureNameMaxSize)
    {
        throw new ApplicationException(string.Format(
            CultureInfo.InvariantCulture, 
            "{0} is an invalid culture name for currency as it is too long.", 
            cultureNameMaxSize));
    }

    String paddedName = cultureName.PadRight(cultureNameMaxSize, '\0');
    for (int i = 0; i < cultureNameMaxSize; i++)
    {
        w.Write(paddedName[i]);
    }

    // Normalize decimal value to two places
    currencyValue = Decimal.Floor(currencyValue * 100) / 100;
    w.Write(currencyValue);
}
public void Read(System.IO.BinaryReader r)
{
    char[] name = r.ReadChars(cultureNameMaxSize);
    int stringEnd = Array.IndexOf(name, '\0');

    if (stringEnd == 0)
    {
        cultureName = null;
        return;
    }

    cultureName = new String(name, 0, stringEnd);
    currencyValue = r.ReadDecimal();
}

Zakończenie kodu dla Currency UDT, zobacz Considerations for Installing SQL Server Samples and Sample Databases.