Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
逃逸';在Access SQL中_Sql_Vba_Ms Access_Escaping - Fatal编程技术网

逃逸';在Access SQL中

逃逸';在Access SQL中,sql,vba,ms-access,escaping,Sql,Vba,Ms Access,Escaping,我尝试在vba中使用以下内容进行域查找: DLookup("island", "villages", "village = '" & txtVillage & "'") 在txtVillage类似于Dillon's Bay之前,这一切都很好,当撇号被视为一个单引号时,我得到了一个运行时错误 我编写了一个不需要单引号的简单函数,它用“.”替换“.”。这似乎是经常出现的问题,但我找不到任何对具有相同功能的内置函数的引用。我错过什么了吗?比你想象的更糟。想一想如果有人输入这样的值,而

我尝试在vba中使用以下内容进行域查找:

DLookup("island", "villages", "village = '" & txtVillage & "'")
在txtVillage类似于Dillon's Bay之前,这一切都很好,当撇号被视为一个单引号时,我得到了一个运行时错误


我编写了一个不需要单引号的简单函数,它用“.”替换“.”。这似乎是经常出现的问题,但我找不到任何对具有相同功能的内置函数的引用。我错过什么了吗?

比你想象的更糟。想一想如果有人输入这样的值,而您没有逃过任何惩罚,会发生什么:

'); DROP TABLE [YourTable]
不漂亮

没有简单转义撇号的内置函数的原因是,正确的处理方法是使用查询参数。对于Ole/Access样式的查询,您可以将其设置为查询字符串:

DLookup("island", "village", "village = ? ")

然后分别设置参数。不过,我不知道如何从vba设置参数值。

顺便说一句,这是我的EscapeQuotes函数

Public Function EscapeQuotes(s As String) As String

    If s = "" Then
        EscapeQuotes = ""
    ElseIf Left(s, 1) = "'" Then
        EscapeQuotes = "''" & EscapeQuotes(Mid(s, 2))
    Else
        EscapeQuotes = Left(s, 1) & EscapeQuotes(Mid(s, 2))
    End If

End Function
“Replace”函数应该可以做到这一点。根据上述代码:

DLookup("island", "villages", "village = '" & Replace(txtVillage, "'", "''") & "'")

我相信access可以使用Chr$(34)并且很高兴在里面有单引号/撇号。
乙二醇

尽管如此,你还是要逃过chr$(34)(“”)

您可以使用Replace函数

Dim escapedString as String

escapedString = Replace(nonescapedString, "'", "''")

虽然像DLookup这样的速记域函数很吸引人,但它们也有缺点

SELECT FIRST(island)
FROM villages
WHERE village = ?;
如果您有多个匹配的候选项,它将选择“第一个”,对于Jet/ACE引擎IIRC,“第一个”的定义依赖于实现(SQL引擎),并且未定义。您知道哪一个将是第一个吗?如果您不这样做,请避开DLookup:)

[出于兴趣,Jet/ACE的答案将是基于上次压缩数据库文件时的clusterd索引的最小值或第一个(有效时间)如果数据库从未压缩过,则插入值。如果存在唯一约束或在非空列上定义的索引,则聚集索引依次由PRIAMRY键确定,否则为第一个(有效时间)插入的行。如果在非空列上定义了多个唯一约束或索引,那么哪一个将用于群集?我不知道!我相信您会认为“第一个”不容易确定,即使您知道如何确定!]

我还看到了Microsoft的建议,即从优化的角度避免使用域聚合函数:

有关Access数据库中查询性能的信息

“避免使用域聚合函数,例如DLookup函数。。。Jet数据库引擎无法优化使用域聚合函数的查询“

如果您选择使用查询重新编写,则可以利用参数语法,或者您可能更喜欢Jet 4.0/ACE过程语法,例如

CREATE PROCEDURE GetUniqueIslandName
(
   :village_name VARCHAR(60)
)
AS 
SELECT V1.island_name
  FROM Villages AS V1
 WHERE V1.village_name = :village_name
       AND EXISTS 
       (
        SELECT V2.village_name
          FROM Villages AS V2
         WHERE V2.village_name = V1.village_name
         GROUP 
            BY V2.village_name
        HAVING COUNT(*) = 1
       );

通过这种方式,您可以使用引擎自己的功能——或者至少是它的数据提供程序的功能——来转义所有字符(而不仅仅是双引号和单引号)必要时。

像Joel Coehoorn建议的参数化查询是一种方法,而不是在查询字符串中进行串联。首先-避免某些安全风险,其次-我合理地确定它需要转义到引擎自己手中,您不必担心这一点。

对于那些在单引号和d替换功能,此行可能会节省您的时间^o^

Replace(result, "'", "''", , , vbBinaryCompare)

在可能有撇号的条件周围放上括号

比如:

DLookup("island", "villages", "village = '[" & txtVillage & "]'")
它们可能需要在单引号之外,或者在TXT村庄附近,如:

DLookup("island", "villages", "village = '" & [txtVillage] & "'")
但是如果你找到了正确的组合,它将处理撇号


Keith B

我的解决方案更简单。最初,我使用此SQL表达式创建ADO记录集:

Dim sSQL as String
sSQL="SELECT * FROM tblTranslation WHERE fldEnglish='" & myString & "';"
myString
中有一个撇号时,就像国际电气公司一样,我的程序就会停止。使用双引号解决了这个问题

sSQL="SELECT * FROM tblTranslation WHERE fldEnglish="" & myString & "";"

但是,它应该是这样的(每个都有一个双引号):

或者我更喜欢:

创建一个函数来转义单引号,因为带“[]”的“转义”将不允许字符串中包含这些字符

Public Function fncSQLStr(varStr As Variant) As String

If IsNull(varStr) Then
        fncSQLStr = ""
    Else
        fncSQLStr = Replace(Trim(varStr), "'", "''")
    End If

End Function
我将此函数用于所有SQL查询,如SELECT、INSERT和UPDATE(以及WHERE子句中的…)


这就是我真正想要的。我不太使用vba,而且我觉得帮助文件也没有多大帮助!干杯。请注意,旧版本的Access(即Access 97)中似乎不存在Replace()。Replace()是在Access 2000中引入的。@David W.Fenton:只要添加一个注释来消除您对Access 2000使用的歧义,如果您同意的话:)替换()函数是在VBA6中引入的。VBA6是从Access2000开始引入Access UI的。Access数据库引擎SQL不支持“替换”函数,无论是本机还是通过Jet Expression Services。在SQL中使用replace()仅在使用Access UI时有效(尽管我承认我不知道如何使用),否则将显示语法错误…因此,最好避免使用Replace()在持久化数据库对象中,例如查询/视图/过程,尤其是验证规则和检查约束。如何单独设置参数?使用准备好的语句。请参阅或。那篇文章是关于SQL Server的,但我怀疑它可能也适用于Access。是的,因此,您现在有了双引号,而不是撇号问题-问题:-/
sSQL = "SELECT * FROM tblTranslation WHERE fldEnglish=""" & myString & """;"
Public Function fncSQLStr(varStr As Variant) As String

If IsNull(varStr) Then
        fncSQLStr = ""
    Else
        fncSQLStr = Replace(Trim(varStr), "'", "''")
    End If

End Function
strSQL = "INSERT INTO tbl" & 
    " (fld1, fld2)" & _
    " VALUES ('" & fncSQLStr(str1) & "', '" & fncSQLStr(Me.tfFld2.Value) & "');"
strSQL = "UPDATE tbl" & _
    " SET fld1='" & fncSQLStr(str1) & "', fld2='" & fncSQLStr(Me.tfFld2.Value) & "'" & _
    " WHERE fld3='" & fncSQLStr(str3) & "';"