Benutzerdefinierte Funktionen
Die meisten Datenbanken nutzen einen prozeduralen Dialekt von SQL, mit dem Sie eigene Funktionen definieren können. SQLite wird jedoch prozessintern mit ihrer App ausgeführt. Anstatt einen neuen Dialekt von SQL erlernen zu müssen, können Sie einfach die Programmiersprache Ihrer App verwenden.
Skalarfunktionen
Skalarfunktionen geben einen einzelnen Skalarwert für jede Zeile in einer Abfrage zurück. Definieren Sie mithilfe von CreateFunction neue Skalarfunktionen, und überschreiben Sie die integrierten.
Eine Liste der unterstützten Parameter und Rückgabetypen für das func
-Argument finden Sie unter Datentypen.
Wenn Sie das state
-Argument angeben, wird dieser Wert an jeden Aufruf der Funktion übergeben. Verwenden Sie dieses, um Abschlüsse zu vermeiden.
Geben Sie isDeterministic
an, wenn Ihre Funktion deterministisch ist, damit SQLite bei der Kompilierung von Abfragen zusätzliche Optimierungen anwenden kann.
Im folgenden Beispiel wird gezeigt, wie Sie eine Skalarfunktion hinzufügen, um den Radius eines Zylinders zu berechnen.
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
";
Operatoren
Die folgenden SQLite-Operatoren werden durch entsprechende Skalarfunktionen implementiert. Wenn Sie diese Skalarfunktionen in Ihrer App definieren, wird das Verhalten dieser Operatoren überschrieben.
Operator | Funktion |
---|---|
X GLOB Y | glob(Y, X) |
X LIKE Y | like(Y, X) |
X LIKE Y ESCAPE Z | like(Y, X, Z) |
X MATCH Y | match(Y, X) |
X REGEXP Y | regexp(Y, X) |
Im folgenden Beispiel wird veranschaulicht, wie die RegEx-Funktion definiert wird, um den entsprechenden Operator zu aktivieren. SQLite enthält keine Standardimplementierung der RegEx-Funktion.
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();
Aggregatfunktionen
Aggregatfunktionen geben einen einzelnen aggregierten Wert für alle Zeilen in einer Abfrage zurück. Definieren und überschreiben Sie Aggregatfunktionen mithilfe von CreateAggregate.
Das seed
-Argument gibt den ursprünglichen Zustand des Kontexts an. Verwenden Sie dieses auch, um Abschlüsse zu vermeiden.
Das func
-Argument wird einmal pro Zeile aufgerufen. Verwenden Sie den Kontext, um ein Endergebnis zu akkumulieren. Geben Sie den Kontext zurück. Mit diesem Muster ist es möglich, dass der Kontext oder ein Werttyp unveränderlich wird.
Wenn resultSelector
nicht angegeben wird, wird der endgültige Zustand des Kontexts als Ergebnis verwendet. Dadurch kann die Definition von Funktionen wie sum und count vereinfacht werden, die jeweils nur eine Zahl für jede Zeile erhöhen und zurückgeben müssen.
Geben Sie resultSelector
an, um das Endergebnis aus dem Kontext zu berechnen, nachdem Sie alle Zeilen durchlaufen haben.
Eine Liste der unterstützten Parameter für das func
-Argument und der Rückgabetypen für resultSelector
finden Sie unter Datentypen.
Geben Sie isDeterministic
an, wenn Ihre Funktion deterministisch ist, damit SQLite bei der Kompilierung von Abfragen zusätzliche Optimierungen anwenden kann.
Im folgenden Beispiel wird eine Aggregatfunktion definiert, um die Standardabweichung einer Spalte zu berechnen.
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();
Fehler
Wenn eine benutzerdefinierte Funktion eine Ausnahme auslöst, wird die Meldung an SQLite zurückgegeben. SQLite löst dann einen Fehler aus, und Microsoft.Data.Sqlite löst eine SqliteException-Ausnahme aus. Weitere Informationen finden Sie unter Datenbankfehler.
Standardmäßig lautet der SQLite-Fehlercode SQLITE_ERROR (oder 1). Sie können diesen jedoch ändern, indem Sie eine SqliteException-Ausnahme in ihrer Funktion mit dem gewünschten SqliteErrorCode-Fehlercode auslösen.
Debuggen
SQLite ruft Ihre Implementierung direkt auf. Auf diese Weise können Sie Breakpoints hinzufügen, die beim Auswerten von Abfragen durch SQLite auslöst werden. Die vollständige .NET-Debuggingfunktion ist verfügbar, um Sie beim Erstellen benutzerdefinierter Funktionen zu unterstützen.