用户定义的函数

大多数数据库都有 SQL 的过程方言,可用于定义自己的函数。 SQLite 是在应用程序进程内运行的。 无需学习新的 SQL 方言,只需使用应用的编程语言即可。

标量函数

标量函数为查询中的每个行返回单个标量值。 定义新的标量函数,并使用 CreateFunction 覆盖内置函数。

有关支持的参数列表和参数的返回类型,请参阅func

指定 state 参数会将该值传递到函数的每个调用中。 使用此选项可避免关闭。

指定 isDeterministic 函数是否确定性,以允许 SQLite 在编译查询时使用其他优化。

以下示例演示如何添加标量函数以计算柱形的半径。

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();

聚合函数

聚合函数返回查询中所有行的单个聚合值。 使用 CreateAggregate.. 定义和替代聚合函数。

seed 参数指定上下文的初始状态。 使用它也可以避免闭包。

每个 func 行调用一次该参数。 使用上下文累积最终结果。 返回上下文。 此模式允许上下文为值类型或不可变。

resultSelector如果未指定,则上下文的最终状态将用作结果。 这可以简化函数的定义,如总和计数,只需递增每个行的数字并返回它。

指定 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)。 但是,可以通过在函数中引发 SqliteException 并指定所需的 SqliteErrorCode 来更改它。

调试

SQLite 直接调用你的实现。 这使你可以添加在 SQLite 评估查询时触发的断点。 提供完整的 .NET 调试体验,可帮助你创建用户定义的函数。

另请参阅