让 SQLite.NET 支持 REGEXP 及自定义函数
SQLite 是免费、开源的内嵌式文件数据库,不需要服务器端,也没有客户端的限制,采用的是内嵌方式或者是动态链接,用来访问和改写数据库文件。SQLite 是许多操作系统(如安卓和Linux)的默认数据库,比微软的 ACCESS 高不知道哪里去。
目前最新版的 SQLite 已支持许多流行的查询函数,比如
JSON
和 REGEXP
等。其中 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
表示为聚合函数,用于循环迭代所有行(比如count
、sum
等函数);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) | 窗口聚合函数相关 |
like
字符匹配,就可以自己写一个类似的字符匹配函数,自己进行字符匹配规则。总之,就发挥你们自己的想象力吧。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。