ほとんどのデータベースには、独自の関数を定義するために使用できる SQL の手続き型方言があります。 ただし、SQLite はアプリでインプロセスで実行されます。 SQL の新しい方言を学ぶ代わりに、アプリのプログラミング言語のみを使用できます。
スカラー関数
スカラー関数は、クエリ内の各行に対して 1 つのスカラー値を返します。 CreateFunctionを使用して、新しいスカラー関数を定義し、組み込みのスカラー関数をオーバーライドします。
func
引数でサポートされているパラメーターと戻り値の型の一覧については、「データ型」を参照してください。
state
引数を指定すると、その値が関数のすべての呼び出しに渡されます。 クロージャを回避するには、これを使用します。
関数が決定論的で、SQLite がクエリのコンパイル時に追加の最適化を使用できるようにする場合は、 isDeterministic
を指定します。
次の例は、円柱の半径を計算するスカラー関数を追加する方法を示しています。
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
";
オペレーター
次の SQLite 演算子は、対応するスカラー関数によって実装されます。 アプリでこれらのスカラー関数を定義すると、これらの演算子の動作がオーバーライドされます。
オペレーター | 機能 |
---|---|
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) |
次の例は、regexp 関数を定義して対応する演算子を有効にする方法を示しています。 SQLite には、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();
集計関数
集計関数は、クエリ内のすべての行に対して 1 つの集計値を返します。 CreateAggregateを使用して集計関数を定義およびオーバーライドします。
seed
引数は、コンテキストの初期状態を指定します。 これを使用して、クロージャも回避します。
func
引数は行ごとに 1 回呼び出されます。 コンテキストを使用して最終的な結果を蓄積します。 コンテキストを返します。 このパターンにより、コンテキストを値型または不変にすることができます。
resultSelector
が指定されていない場合は、コンテキストの最終的な状態が結果として使用されます。 これにより、行ごとに数値をインクリメントして返すだけで済む sum や count などの関数の定義を簡略化できます。
すべての行を反復処理した後、コンテキストから最終的な結果を計算する resultSelector
を指定します。
func
引数でサポートされているパラメーター型の一覧と、resultSelector
の戻り値の型については、「データ型」を参照してください。
関数が決定論的な場合は、 isDeterministic
を指定して、SQLite がクエリのコンパイル時に追加の最適化を使用できるようにします。
次の例では、列の標準偏差を計算する集計関数を定義します。
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();
エラー
ユーザー定義関数が例外をスローした場合、メッセージは SQLite に返されます。 SQLite はエラーを発生させ、Microsoft.Data.Sqlite は SqliteException をスローします。 詳細については、「 データベース エラー」を参照してください。
既定では、エラー SQLite エラー コードはSQLITE_ERROR (または 1) になります。 ただし、目的のSqliteErrorCodeを指定して関数にSqliteExceptionをスローすることで変更できます。
デバッグ
SQLite は実装を直接呼び出します。 これにより、SQLite がクエリを評価している間にトリガーされるブレークポイントを追加できます。 完全な .NET デバッグ エクスペリエンスは、ユーザー定義関数の作成に役立ちます。
こちらも参照ください
.NET