在 MS Access DB 中存储正则表达式会杀死功能
Posted
技术标签:
【中文标题】在 MS Access DB 中存储正则表达式会杀死功能【英文标题】:Storing regex in MS Access DB kills functionality 【发布时间】:2014-01-16 19:31:02 【问题描述】:我有一个 MS Access 数据库和一个 function (感谢 @MPękalski),它由联接中的查询调用
create table OSS_File(
id number,
Kw text(255));
insert into OSS_File(ID,kw) values(1,"black or white");
insert into OSS_File(ID,kw) values(2,"green");
insert into OSS_File(ID,kw) values(3,"blue berry");
insert into OSS_File(ID,kw) values(4,"blueberry");
insert into OSS_File(ID,kw) values(5,"bluegreen");
insert into OSS_File(ID,kw) values(6,"yellow");
create table restricted_words(
restricted_word text(255));
insert into restricted_words(restricted_word) values("\bblack\b");
insert into restricted_words(restricted_word) values("^green$");
insert into restricted_words(restricted_word) values("^blue[ ]?berry$");
insert into restricted_words(restricted_word) values("yellow");
Function my_regexp(ByRef sIn As String, ByVal mypattern As String) As String
Dim r As New RegExp
Dim colMatches As MatchCollection
With r
.Pattern = mypattern
.IgnoreCase = True
.Global = False
.MultiLine = False
Set colMatches = .Execute(sIn)
End With
If colMatches.Count > 0 Then
my_regexp = colMatches(0).Value
Else
my_regexp = ""
End If
End Function
SELECT restricted_words.restricted_word, OSS_File.ID, OSS_File.kw
FROM restricted_words INNER JOIN OSS_File
ON restricted_words.restricted_word=my_regexp(nz(OSS_File.kw),restricted_words.restricted_word);
我本来希望得到除了 ID #5 之外的所有东西,但我只得到了 #6。 但是,如果我删除 ^、$ 或 \b,我会重写函数,如
.Pattern = "^" & mypattern & "$"
or
.Pattern = "\b" & mypattern & "\b"
我可以取回结果(除了“blue[ ]?berry”,因为 [ ]?)。
为什么当整个正则表达式存储在表中时,mach 会失败?
【问题讨论】:
"\b" 可能是退格字符。一般来说,你必须逃避所有的逃跑,还是Vba不同?什么是空字符类[ ]
?
尝试在with
块之前插入Msgbox mypattern
,以便仔细检查其中包含的内容。
@sln [ ]?是一个非必需的空间来匹配蓝莓和蓝莓(我不写规范,我只需要对它们进行编程:))
@sln \\bblack\\b 也好不到哪里去。
@BernardSaucier 我使用了 Debug.Print r.Pattern,它是正确的
【参考方案1】:
您加入的ON
子句...
ON
restricted_words.restricted_word
=
my_regexp(nz(OSS_File.kw),restricted_words.restricted_word);
restricted_word
是一个正则表达式模式,例如"^blue[ ]?berry$"
在该联接的右侧,您要求提供函数的返回值,例如 "blue berry"
。
模式与基于该模式的函数返回值不匹配。
考虑一种不同的方法。
FROM restricted_words AS r, OSS_File AS o
WHERE my_regexp_test(o.kw, r.restricted_word) = True
这是在立即窗口中测试的功能。
? my_regexp_test("blue berry", "^blue[ ]?berry$")
True
? my_regexp_test("blueberry", "^blue[ ]?berry$")
True
? my_regexp_test("strawberry", "^blue[ ]?berry$")
False
Function my_regexp_test(ByRef sIn As String,
ByVal mypattern As String) As Boolean
Dim r As New RegExp
With r
.pattern = mypattern
.IgnoreCase = True
.Global = False
.Multiline = False
End With
my_regexp_test = r.Test(sIn)
End Function
【讨论】:
SELECT DISTINCT o.ID, o.kw FROM restricted_words as r, OSS_File as o WHERE (((my_regexp_test(nz(o.kw),r.restricted_word))=True));像宣传的那样工作。但是,我想要哪个模式标记了关键字 (kw) SELECT r.restricted_word, o.ID, o.kw FROM restricted_words r, OSS_File o WHERE (((my_regexp(nz(o.kw),r.restricted_word))=True ));返回一个笛卡尔积,所以我需要继续努力。感谢您为我指明正确的方向【参考方案2】:正如@HansUp 所指出的,我的“ON”两边从未匹配,所以我所做的是,如果匹配,我返回原始 sIn (OSS_File.kw) 字符串,如果没有,我返回“”(除非 sIn 是"" 开头所以我返回 x) 然后我把 OSS_File.kw 放在 on 的左侧。
Function my_regexp(ByRef sIn As String, ByVal mypattern As String) As String
Dim r As New RegExp
Dim colMatches As MatchCollection
With r
.Pattern = mypattern
.IgnoreCase = True
.Global = False
.MultiLine = False
Set colMatches = .Execute(sIn)
End With
If colMatches.Count > 0 Then
my_regexp = sIn
ElseIf sIn = "" Then
my_regexp = "x"
Else
my_regexp = ""
End If
End Function
SELECT restricted_words.restricted_word, OSS_File.ID, OSS_File.kw
FROM restricted_words INNER JOIN OSS_File ON OSS_File.kw=my_regexp(nz(OSS_File.kw),restricted_words.restricted_word);
再次感谢大家
【讨论】:
以上是关于在 MS Access DB 中存储正则表达式会杀死功能的主要内容,如果未能解决你的问题,请参考以下文章
为了对存储在 Oracle db 中的数据运行搜索查询,在 PL/SQL 中使用 REGEXP 是不是比在 Java 正则表达式中获取所有数据并过滤它更快?
VS Lightswitch 和 MS Access DB?