访问VBA,未转义的单引号,Replace()和null

时间:2011-08-01 02:56:28

标签: database ms-access null replace access-vba

在Microsoft VBA中处理脚本以获取大量平面数据库并将其拆分为大约20个不同的表。该脚本主要包括打开一个表,检查平面数据库中的每一行以确保它不是重复的,然后添加必要的字段。对每张桌子重复一遍。

我第一次运行它一切顺利,直到我尝试处理名称O'Malley。我认为很明显出了什么问题。 Google上的快速搜索出现了this related StackOverflow post。我接受了他们的建议并在将Replace(str, "'", "''")添加到每个字段之前将其输入到新表中。现在我遇到了一个新问题,谷歌的帮助不大。

Replace(null, "'", "''")会导致运行时错误,而flat数据库只会出现空值。我可以在每次 Replace()调用之上添加额外的行以检查IsNull(),如果是,则将null放入数据库而不是Replace(str, "'", "''"),尽管我如果可能的话,我更喜欢能够融入一条线的解决方案。有没有更优雅的方法来解决这个难题,还是我的代码中需要216个If语句?

编辑 -

我正在寻找更优雅的解决方案的另一个原因是我的重复检查代码。目前我有以下内容:

        'Check for duplicates
        'Assume student is duplicate if it shares:
        '   (StudentName and School) or SSN
        Set rstDuplicate = CurrentDb.OpenRecordset("select * from Student where (StudentName = '" & Replace(rstFrom("Student").Value, "'", "''") & "' AND School = '" & Replace(rstFrom("School").Value, "'", "''") & "') OR SSN = '" & Replace(rstFrom("Social").Value, "'", "''") & "'")
        If rstDuplicate.RecordCount = 0 Then
            'Duplicate was not found
            rstTo.AddNew
            ' Add fields to the new table
            rstTo.Update
        End If

由于Replace()调用与重复检查内联,如果我使用If语句来检查null,那么我必须将结果保存到字符串或更新到平面数据库。在不需要额外变量的情况下返回Replace(str, "'", "''") OR null的函数将是理想的。

3 个答案:

答案 0 :(得分:1)

如果你想保持所有内联,你可以使用立即If函数(IIf):

IIf(IsNull(rstFrom("Student").Value), " Is Null", "= " & Replace(rstFrom("Student").Value)
但是,这将是一个阅读和维护的噩梦。你最好编写自己的函数来处理比较运算符的变化以及撇号转义:

Function CompFld(Val As Variant) As String
    If IsNull(Val) Then
        CompFld = " Is Null "
    Else
        CompFld = "= '" & Replace(Val, "'", "''") & "' "
    End If
End Function

使用它:

Dim SQL As String
SQL = "SELECT * FROM Student " & _
      "WHERE (StudentName " & CompFld(rstFrom("Student").Value) & " AND " & _
      "       School " & CompFld(rstFrom("School").Value) & ") " & _
      "   OR (SSN " & CompFld(rstFrom("Social").Value) & ") "
Set rstDuplicate = CurrentDb.OpenRecordset(SQL)
If rstDuplicate.RecordCount = 0 Then
    'Duplicate was not found
    rstTo.AddNew
    ' Add fields to the new table
    rstTo.Update
End If

答案 1 :(得分:1)

很久以前传给我的一个简洁而又丑陋的小宝石:

Replace(str & "", "'", "''")

将空字符串附加到空值会在VBA中返回空字符串,并且不会修改非空字符串。

答案 2 :(得分:1)

Access'数据库引擎将接受单引号或双引号作为查询中字符串值的分隔符。所以不是......

SELECT * FROM Student WHERE StudentName = 'O''Malley'

......你可以这样做......

SELECT * FROM Student WHERE StudentName = "O'Malley"

这将允许您处理包含撇号的输入。 OTOH,如果你的字符串输入也包含双引号,这将打破。

我怀疑你可能有更多的事情发生,而不仅仅是撇号问题,但我不明白你的大局。您似乎正在为rstFrom中的每条记录打开第三个DAO记录集,以检查Student表中是否存在匹配项。我会改用DCount()

Dim strCriteria As String
strCriteria = "StudentName = ""O'Malley"" AND School = ""foo"""
If DCount("*", "Student", strCriteria) = 0 Then
    'no match found --> add it '
End If