SQLite 是免费、开源的内嵌式文件数据库,不需要服务器端,也没有客户端的限制,采用的是内嵌方式或者是动态链接,用来访问和改写数据库文件。SQLite 是许多操作系统(如安卓和Linux)的默认数据库,比微软的 ACCESS 高不知道哪里去。

目前最新版的 SQLite 已支持许多流行的查询函数,比如 JSONREGEXP 等。其中 REGEXP 可以对字段进行正则匹配,JSON 则是可以直接读写JSON格式的文本内容。
然而目前 SQLite 的 .NET 版本仅支持 JSON 相关函数,REGEXP 的正则匹配函数并不支持。

好在 SQLite 的扩展性非常高,我们可以自行为 SQLite 添加函数,用于补齐 SQLite.NET 内不支持的函数。
并且,由于我们采用 .NET 的正则处理类,所以我们可以使用更加标准的正则语法,而非 SQLite 较为“畸形”和不便的原生规则。

一个委托类实例:
' REGEXP 函数的委托类
<SQLiteFunction(Name:="REGEXP", Arguments:=2, FuncType:=FunctionType.Scalar)>
Public Class SQLiteRegexP
    Inherits SQLiteFunction

    ' 函数的委托方法
    Public Overrides Function Invoke(ByVal args() As Object) As Object
        Dim ret = Regex.IsMatch(Convert.ToString(args(1)), Convert.ToString(args(0)), RegexOptions.IgnoreCase)
        Return ret
    End Function
End Class

' 在任何初始化函数中注册我们的委托类,比如 Sub Main \ Sub New \ Loading 等事件
Sub Main()
    SQLiteFunction.RegisterFunction(GetType(SQLiteRegexP))
    ' 其他代码...
End Sub
SQLite 的委托类只需要继承 SQLiteFunction 即可,再通过类型描述为其添加元数据,其中的 Name:="xxx" 来设置类型在 SQLite 当中的函数名称,Arguments:=2 限定函数的参数数量(如果是动态参数就不要设定)。
FuncType:=FunctionType.Scalar 表示这个类型为“标量函数”(执行后立刻返回某个值);
FuncType:=FunctionType.Aggregate 表示为聚合函数,用于循环迭代所有行(比如countsum等函数);
FuncType:=FunctionType.Collation 表示为文本排序方法,用于 ORDER BY 后面执行自定义的排序规则。

因为我们的 REGEXP 只是一般的函数,所以用 Scalar 即可,同时需要重写 SQLiteFunction.Invoke 方法。
当在 SQLite 查询中激活我们自定义的 REGEXP 函数后,即可激活我们重写的 Invoke 方法。

当实现委托类型和方法后,使用 SQLiteFunction.RegisterFunction 注册委托类,之后我们就可以在SQL查询语句中使用我们的自定义函数了。只不过我们调用函数的时候,需要谨记:如果使用的是 字段 函数 参数... 的调用方法,则右侧参数的优先级比左侧高,也就是参数优先级比字段要高。
字段 函数 参数... 会被转化为 函数(参数..., 字段) 来进行调用,所以在 Invoke 方法中,字段的位置在 args(1) 而不是 args(0)
当然,你也可以使用一般函数的调用方法来调用我们的自定义函数。

SQLite查询示例:
-- 对字段进行正则匹配
-- 简化写法
select * from 表 where 字段 regexp '正则表达式'
-- 其他写法
select * from 表 where regexp('正则表达式', 字段) = 1
select * from 表 where regexp('正则表达式', 字段) > 0
SQLite 中的布尔值采用0和1进行存储,所以我们对 REGEXP 的返回值进行数值判断即可。
再因为右侧参数优先的规则,所以我们需要将字段参数放到最后一个位置。
有了上面的示例,我们写其他函数也会非常容易,不过针对不同的函数,需要重写不同的方法:
函数参数说明
Invoke(ByVal args() As Object) As Object调用时触发,右侧参数优先级更高
Final(ByVal contextData As Object) As Object聚合函数
Step(ByVal args() As Object, ByVal stepNumber As Integer, ByRef contextData As Object)聚合函数会重载此方法
Compare(ByVal param1 As String, ByVal param2 As String) As Integer自定义字符排序
参数1大返回1,平返回0,否返回-1
Value(ByVal contextData As Object) As Object窗口聚合函数相关
Inverse(ByVal args() As Object, ByVal stepNumber As Integer, ByRef contextData As Object)窗口聚合函数相关
比如你不喜欢SQL的 like 字符匹配,就可以自己写一个类似的字符匹配函数,自己进行字符匹配规则。
总之,就发挥你们自己的想象力吧。