Udostępnij za pośrednictwem


Funkcje zdefiniowane przez użytkownika

Większość baz danych ma proceduralny dialekt SQL, którego można użyć do zdefiniowania własnych funkcji. SqLite uruchamia jednak proces w aplikacji. Zamiast uczyć się nowego dialektu JĘZYKA SQL, możesz po prostu użyć języka programowania aplikacji.

Funkcje skalarne

Funkcje skalarne zwracają pojedynczą, skalarną wartość dla każdego wiersza w zapytaniu. Zdefiniuj nowe funkcje skalarne i zastąpij wbudowane przy użyciu polecenia CreateFunction.

Zobacz Typy danych, aby uzyskać listę obsługiwanych typów parametrów i zwracanych dla argumentu func .

Określenie argumentu state spowoduje przekazanie tej wartości do każdego wywołania funkcji. Użyj tego polecenia, aby uniknąć zamknięcia.

Określ isDeterministic , czy funkcja jest deterministyczna, aby umożliwić sqlite używanie dodatkowych optymalizacji podczas kompilowania zapytań.

W poniższym przykładzie pokazano, jak dodać funkcję skalarną w celu obliczenia promienia cylindra.

connection.CreateFunction(
    "volume",
    (double radius, double height)
        => Math.PI * Math.Pow(radius, 2) * height);

var command = connection.CreateCommand();
command.CommandText =
@"
    SELECT name,
           volume(radius, height) AS volume
    FROM cylinder
    ORDER BY volume DESC
";

Operatory

Następujące operatory SQLite są implementowane przez odpowiednie funkcje skalarne. Zdefiniowanie tych funkcji skalarnych w aplikacji spowoduje zastąpienie zachowania tych operatorów.

Operator Function
X GLOB Y glob(Y, X)
X LIKE Y like(Y, X)
X LIKE Y ESCAPE Z like(Y, X, Z)
X DOPASOWANIE Y match(Y, X)
X REGEXP Y regexp(Y, X)

W poniższym przykładzie pokazano, jak zdefiniować funkcję regexp w celu włączenia odpowiedniego operatora. SqLite nie zawiera domyślnej implementacji funkcji regexp.

connection.CreateFunction(
    "regexp",
    (string pattern, string input)
        => Regex.IsMatch(input, pattern));

var command = connection.CreateCommand();
command.CommandText =
@"
    SELECT count()
    FROM user
    WHERE bio REGEXP '\w\. {2,}\w'
";
var count = command.ExecuteScalar();

Funkcje agregujące

Funkcje agregujące zwracają pojedynczą zagregowaną wartość dla wszystkich wierszy w zapytaniu. Zdefiniuj i zastąpij funkcje agregujące przy użyciu polecenia CreateAggregate.

Argument seed określa początkowy stan kontekstu. Użyj tej funkcji, aby uniknąć również zamknięcia.

Argument func jest wywoływany raz w każdym wierszu. Użyj kontekstu, aby zebrać końcowy wynik. Zwróć kontekst. Ten wzorzec pozwala kontekstowi być typem wartości lub niezmiennym.

Jeśli nie resultSelector zostanie określony, w wyniku zostanie użyty stan końcowy kontekstu. Może to uprościć definicję funkcji, takich jak suma i liczba, które muszą tylko zwiększać liczbę poszczególnych wierszy i zwracać je.

Określ resultSelector , aby obliczyć wynik końcowy z kontekstu po iterowaniu przez wszystkie wiersze.

Zobacz Typy danych, aby uzyskać listę obsługiwanych typów parametrów dla argumentu func i zwracanych typów dla elementu resultSelector.

Jeśli funkcja jest deterministyczna, określ isDeterministic , aby umożliwić sqlite używanie dodatkowych optymalizacji podczas kompilowania zapytań.

W poniższym przykładzie zdefiniowano funkcję agregacji w celu obliczenia odchylenia standardowego kolumny.

connection.CreateAggregate(
    "stdev",

    // A tuple to maintain context between rows
    (Count: 0, Sum: 0.0, SumOfSquares: 0.0),

    // This is called for each row
    ((int Count, double Sum, double SumOfSquares) context, double value) =>
    {
        context.Count++;
        context.Sum += value;
        context.SumOfSquares += value * value;

        return context;
    },

    // This is called to get the final result
    context =>
    {
        var variance = context.SumOfSquares - context.Sum * context.Sum / context.Count;

        return Math.Sqrt(variance / context.Count);
    });

var command = connection.CreateCommand();
command.CommandText =
@"
    SELECT stdev(gpa)
    FROM student
";
var stdDev = command.ExecuteScalar();

Błędy

Jeśli funkcja zdefiniowana przez użytkownika zgłasza wyjątek, komunikat zostanie zwrócony do sqlite. Narzędzie SQLite zgłosi błąd, a obiekt Microsoft.Data.Sqlite zgłosi wyjątek SqliteException. Aby uzyskać więcej informacji, zobacz Błędy bazy danych.

Domyślnie kod błędu SQLite będzie SQLITE_ERROR (lub 1). Można go jednak zmienić, zgłaszając element SqliteException w funkcji przy użyciu żądanego SqliteErrorCode określonego elementu.

Debugowanie

SqLite wywołuje implementację bezpośrednio. Dzięki temu można dodawać punkty przerwania wyzwalane podczas oceniania zapytań przez sqlite. Pełne środowisko debugowania platformy .NET jest dostępne, aby ułatwić tworzenie funkcji zdefiniowanych przez użytkownika.

Zobacz też