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.