Dela via


CLR-skalärvärdesfunktioner

gäller för:SQL Server

En skalärvärdesfunktion (SVF) returnerar ett enda värde, till exempel ett sträng-, heltals- eller bitvärde. Du kan skapa skalära användardefinierade funktioner i hanterad kod med hjälp av valfritt .NET Framework-programmeringsspråk. Dessa funktioner är tillgängliga för Transact-SQL eller annan hanterad kod. Information om fördelarna med CLR-integrering (Common Language Runtime) och val mellan hanterad kod och Transact-SQL finns i ÖVERSIKT över CLR-integrering.

Krav för CLR-skalärvärdesfunktioner

.NET Framework-SDF:er implementeras som metoder på en klass i en .NET Framework-sammansättning. Indataparametrarna och typen som returneras från en SVF kan vara någon av de skalära datatyper som stöds av SQL Server. förutom varchar, char, rowversion, text, ntext, image, tidsstämpel, tabelleller markören. SDF:er måste säkerställa en matchning mellan SQL Server-datatypen och returdatatypen för implementeringsmetoden. Mer information om typkonverteringar finns i Mappa CLR-parameterdata.

När du implementerar en .NET Framework SVF på ett .NET Framework-språk kan du ange det SqlFunction anpassade attributet för att inkludera ytterligare information om funktionen. Attributet SqlFunction anger om funktionen kommer åt eller ändrar data, om den är deterministisk och om funktionen omfattar flyttalsåtgärder.

Skalärvärdesanvändardefinierade funktioner kan vara deterministiska eller icke-deterministiska. En deterministisk funktion returnerar alltid samma resultat när den anropas med en specifik uppsättning indataparametrar. En icke-deterministisk funktion kan returnera olika resultat när den anropas med en specifik uppsättning indataparametrar.

Not

Markera inte en funktion som deterministisk om funktionen inte alltid genererar samma utdatavärden med samma indatavärden och samma databastillstånd. Om en funktion markeras som deterministisk kan det leda till skadade indexerade vyer och beräknade kolumner när funktionen inte är helt deterministisk. Du markerar en funktion som deterministisk genom att ange egenskapen IsDeterministic till true.

Tabellvärdesparametrar

Tabellvärdesparametrar (TVP:er), användardefinierade tabelltyper som skickas till en procedur eller funktion, ger ett effektivt sätt att skicka flera rader med data till servern. TVP:er har liknande funktioner som parametermatriser, men ger större flexibilitet och närmare integrering med Transact-SQL. De ger också möjlighet till bättre prestanda.

TVP:er bidrar också till att minska antalet tur- och returresor till servern. I stället för att skicka flera begäranden till servern, till exempel med en lista över skalära parametrar, kan data skickas till servern som en TVP. En användardefinierad tabelltyp kan inte skickas som en tabellvärdeparameter till eller returneras från en hanterad lagrad procedur eller funktion som körs i SQL Server-processen. Mer information om TVP:er finns i Använda tabellvärdesparametrar (databasmotor).

Exempel på en CLR-skalärvärdesfunktion

Här är en enkel SVF som kommer åt data och returnerar ett heltalsvärde:

using Microsoft.SqlServer.Server;
using System.Data.SqlClient;

public class T
{
    [SqlFunction(DataAccess = DataAccessKind.Read)]
    public static int ReturnOrderCount()
    {
        using (SqlConnection conn
            = new SqlConnection("context connection=true"))
        {
            conn.Open();
            SqlCommand cmd = new SqlCommand(
                "SELECT COUNT(*) AS 'Order Count' FROM SalesOrderHeader", conn);
            return (int)cmd.ExecuteScalar();
        }
    }
}

Den första kodraden refererar Microsoft.SqlServer.Server till åtkomstattribut och System.Data.SqlClient för att få åtkomst till ADO.NET namnrymd. (Det här namnområdet innehåller SqlClient, .NET Framework Data Provider för SQL Server.)

Sedan tar funktionen emot det anpassade attributet SqlFunction som finns i Microsoft.SqlServer.Server namnrymd. Det anpassade attributet anger om den användardefinierade funktionen (UDF) använder den pågående providern för att läsa data på servern. SQL Server tillåter inte att UDF:er uppdaterar, infogar eller tar bort data. SQL Server kan optimera körningen av en UDF som inte använder den pågående providern. Detta anges genom att ange DataAccessKind till DataAccessKind.None. På nästa rad är målmetoden en offentlig statisk (delad i Visual Basic .NET).

Klassen SqlContext, som finns i namnområdet Microsoft.SqlServer.Server, kan sedan komma åt ett SqlCommand objekt med en anslutning till SQL Server-instansen som redan har konfigurerats. Även om den inte används här är den aktuella transaktionskontexten också tillgänglig via System.Transactions api (Application Programming Interface).

De flesta kodrader i funktionstexten bör se bekanta ut för utvecklare som skriver klientprogram som använder de typer som finns i System.Data.SqlClient namnrymd.

using(SqlConnection conn = new SqlConnection("context connection=true"))
{
   conn.Open();
   SqlCommand cmd = new SqlCommand(
        "SELECT COUNT(*) AS 'Order Count' FROM SalesOrderHeader", conn);
   return (int) cmd.ExecuteScalar();
}

Lämplig kommandotext anges genom att initiera objektet SqlCommand. I föregående exempel räknas antalet rader i tabellen SalesOrderHeader. Därefter anropas metoden ExecuteScalar för det cmd objektet. Detta returnerar ett värde av typen int baserat på frågan. Slutligen returneras orderantalet till anroparen.

Om den här koden sparas i en fil med namnet FirstUdf.cs kan den kompileras till som sammansättning enligt följande:

csc.exe /t:library /out:FirstUdf.dll FirstUdf.cs

/t:library anger att ett bibliotek i stället för en körbar fil ska skapas. Körbara filer kan inte registreras i SQL Server.

Visuella C++-databasobjekt som kompilerats med /clr:pure stöds inte för körning på SQL Server. Sådana databasobjekt innehåller till exempel skalärvärdesfunktioner.

Den Transact-SQL frågan och ett exempelanrop för att registrera sammansättningen och UDF är:

CREATE ASSEMBLY FirstUdf
    FROM 'FirstUdf.dll';
GO

CREATE FUNCTION CountSalesOrderHeader()
RETURNS INT
AS EXTERNAL NAME FirstUdf.T.ReturnOrderCount;
GO

SELECT dbo.CountSalesOrderHeader();
GO

Funktionsnamnet som exponeras i Transact-SQL behöver inte matcha namnet på den offentliga statiska målmetoden.