在 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?

如何在 VBA 代码中的 ms-access 中执行查询?

在 MS Access DB 中创建临时表

如何在 Spring 批处理中读取 MS Access db(.mdb 文件)并加载到 mysql db

如何在线获取静态 MS-Access DB 并使用 PHP 连接到它?