【问题标题】:Apostrophe in memo text causing error in code备忘录文本中的撇号导致代码错误
【发布时间】:2018-07-23 23:13:37
【问题描述】:

我正在使用 Access 2016,但我遇到了一个错误,即更新了备注字段并且人们正在使用撇号,并且它会干扰要更新的代码。该代码运行良好,它会更新表格以获取特定值,除非存在撇号。再多的括号或方括号都无法解决此问题,从而将文本中的撇号与代码隔离开来。如果可能的话,我更喜欢允许我使用撇号的建议。

Private Sub btnlledit_Click()
Dim SQL As String

SQL = "UPDATE tblll " & _
      "SET [LLN] = '" & Forms!frmaddll!txtlln & "',[REF] = '" & Forms!frmaddll!txtllref & "',[TRN] = '" & Forms!frmaddll!txtlltr & "',[HN] = '" & Forms!frmaddll!txtllhull & "', [LL] = '" & Forms!frmaddll!txtll & "',[CA] = '" & Forms!frmaddll!txtllca & "',[CP] = '" & Forms!frmaddll!txtllcomponent & "',[LOC] = '" & Forms!frmaddll!txtllloc & "',[LFSE] = '" & Forms!frmaddll!txtlllfse & "',[FC] = '" & Forms!frmaddll!txtllfc & "' " & _
      "WHERE [LLN] = '" & Forms!frmaddll!txtlln.Value & "';"


DoCmd.RunSQL SQL
DoCmd.Requery

Me.Refresh

End Sub

【问题讨论】:

  • 使用参数。这不仅可以防止 SQL 注入攻击,而且可以从一开始就解决此类问题。作为一个很好的措施,永远不要用字符串连接编写这样的 SQL 语句。
  • 我对编程很陌生,你说的使用参数是什么意思?
  • 我会在一分钟内将其添加为答案。

标签: sql vba apostrophe


【解决方案1】:

我已经削减了你的 SQL 来给你一个想法。

SQL 的第一行是参数 - 请注意第一行末尾的;

Private Sub btnlledit_Click()

    Dim qdf As DAO.QueryDef

    Set qdf = CurrentDb.CreateQueryDef("", _
        "PARAMETERS  LLN_Value TEXT(255), REF_Value TEXT(255), TRN_Value TEXT(255); " & _
        "UPDATE tblll " & _
        "SET LLN = LLN_Value, REF = REF_Value, TRN = TRN_Value " & _
        "WHERE LLN = LLN_Value")

    With qdf
        .Parameters("LLN_Value") = Forms!frmaddll!txtlln
        .Parameters("REF_Value") = Forms!frmaddll!txtllref
        .Parameters("TRN_Value") = Forms!frmaddll!txtlltr
        .Execute
    End With

End Sub  

更好的方法是将查询的执行移至另一个过程并将所需的值传递给该过程:

Public Sub MyQuery(My_LLN_Value AS String, My_Ref_Value AS String, My_TRN_Value AS String)

    Dim qdf As DAO.QueryDef

    Set qdf = CurrentDb.CreateQueryDef("", _
        "PARAMETERS  LLN_Value TEXT(255), REF_Value TEXT(255), TRN_Value TEXT(255); " & _
        "UPDATE tblll " & _
        "SET LLN = LLN_Value, REF = REF_Value, TRN = TRN_Value " & _
        "WHERE LLN = LLN_Value")

    With qdf
        .Parameters("LLN_Value") = My_LLN_Value
        .Parameters("REF_Value") = My_Ref_Value
        .Parameters("TRN_Value") = My_TRN_Value
        .Execute
    End With

End Sub

然后您可以通过单击按钮调用此过程:

Private Sub btnlledit_Click()

    MyQuery Forms!frmaddll!txtlln, Forms!frmaddll!txtllref, Forms!frmaddll!txtlltr

End Sub  

或从其他地方,并从其他地方获取您的价值观:

Public Sub Test

    Dim Second_Arg AS String
    Second_Arg = "Some Reference Value"

    MyQuery Forms!frmaddll!txtlln, Second_Arg, "Third Argument"

End Sub

【讨论】:

  • 我将第一个复制并粘贴到访问权限中,只是尝试启动代码以确保我可以运行它,当我使用定义的参数单击编辑时,这 3 个值不会产生更新更改和编辑。我需要更多地改变它吗?一旦我可以更好地设置参数,我可能会使用建议的拆分。
  • 我不确定您所说的 当我使用定义的参数单击编辑时,这 3 个值在更改和编辑时不会产生更新。你在什么上点击了edit?我想首先要问的是 - 所有参数都是文本字段吗?最可能的参数数据类型是:文本字符串 - TEXT(255)、Yes/No(Boolean) - Bit、日期 - DateTime,长整型 - Long,双精度值 - 双精度。您的表单引用是否正确返回值?
  • 也正如@CetinBasoz 所说 - 您正在设置 LLN 的值,同时将返回的结果限制为该值。这可能是没有返回结果的原因 - 如果您的表在更新之前不包含匹配 Forms!frmaddll!txtlln 的 LLN 值,那么它将无法更新任何内容。
  • 单击编辑是单击以运行所有内容的按钮,所有内容都是文本字段,但并非所有限制都是 255 个字符。表格参考是正确的。我在开会,我要多看一下代码,看看我做错了什么。
【解决方案2】:

我马上说,但还有其他东西(+ 在 VBA 中写这个是一种折磨):

Dim SQL As String

SQL = "UPDATE tblll " & _
      "SET [REF] = @ref,[TRN] = @trn,[HN] = @hn" & _
      ", [LL] = @ll,[CA] = @ca,[CP] = @cp,[LOC] = @loc " & _
      ", [LFSE] = @lfse, [FC] = @fc" & _
      "WHERE [LLN] = @lln";"

   Dim oConnection As ADODB.Connection
   Dim oCommand As ADODB.Command

  Set oConnection = New ADODB.Connection
  Set oCommand = New ADODB.Command

  oConnection.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\MyFolder\MyData.accdb;"

  oConnection.Open
  oCommand.ActiveConnection = oConnection
  oCommand.CommandText = SQL


  oCommand.Parameters.Append oCommand.CreateParameter("@ref", adInteger)
  oCommand.Parameters.Append oCommand.CreateParameter("@trn", adVarChar, adParamInput, 100)
  oCommand.Parameters.Append oCommand.CreateParameter("@hn", adInteger)
  oCommand.Parameters.Append oCommand.CreateParameter("@ll", adInteger)
  oCommand.Parameters.Append oCommand.CreateParameter("@ca", adInteger)
  oCommand.Parameters.Append oCommand.CreateParameter("@cp", adInteger)
  oCommand.Parameters.Append oCommand.CreateParameter("@loc", adInteger)
  oCommand.Parameters.Append oCommand.CreateParameter("@lfse", adInteger)
  oCommand.Parameters.Append oCommand.CreateParameter("@fc", adInteger)
  oCommand.Parameters.Append oCommand.CreateParameter("@lln", adInteger)

  oCommand.Parameters("@ref" ).Value = Forms!frmaddll!txtref.Value
  oCommand.Parameters("@trn" ).Value = Forms!frmaddll!txttrn.Value
  oCommand.Parameters("@hn"  ).Value = Forms!frmaddll!txthn.Value
  oCommand.Parameters("@ll"  ).Value = Forms!frmaddll!txtll.Value
  oCommand.Parameters("@ca"  ).Value = Forms!frmaddll!txtca.Value
  oCommand.Parameters("@cp"  ).Value = Forms!frmaddll!txtcp.Value
  oCommand.Parameters("@loc" ).Value = Forms!frmaddll!txtloc.Value
  oCommand.Parameters("@lfse").Value = Forms!frmaddll!txtlfse.Value
  oCommand.Parameters("@fc"  ).Value = Forms!frmaddll!txtfc.Value
  oCommand.Parameters("@lln" ).Value = Forms!frmaddll!txtlln.Value

  oCmd.Execute

此代码不是专门的访问代码,而是 VBA(您可以在任何 VBA 环境中执行,例如 Excel、Word ...)。 由于我不知道您的字段,因此参数类型仅用于采样。这里重要的是,您必须按照它们在查询字符串中出现的顺序定义参数。附加参数后,您可以按照自己喜欢的任何顺序随意设置它们的值(我认为这是驱动程序的一个限制,参数不是命名的而是位置的)。

注意:我删除了初始 LLN= 因为您正在搜索它并设置为相同的值(IOW 没有变化)。

【讨论】:

  • 我的访问在这里很奇怪,不允许我使用 ADODB。由于当前数据库的限制,我可能必须创建一个新数据库并将其转移以运行它。稍后我会告诉你结果如何。
  • @Kewl147,您可能需要从引用 (Microsoft.ActiveXDataObjects) 添加 ADODB。或者更好的是,帮自己一个忙,使用真正的数据库(以及 VBA 以外的语言)。
  • 我发现我必须从引用中删除并添加一些内容,但是现在我收到一个错误消息,指出该文件当前正在使用或由管理员置于状态。我目前正在配置设置。
【解决方案3】:

单引号通过加倍进行转义,正如您在示例中向我们展示的那样。以下 SQL 说明了此功能。

顺便说一句,使用 SQL 参数而不是这些内联 SQL 注入。

尝试如下:

Private Sub btnlledit_Click()
    Dim SQL As String

    SQL = "UPDATE tblll " & _
          "SET [LLN] = '" & Forms!frmaddll!txtlln & "',[REF] = '" & Forms!frmaddll!txtllref & "',[TRN] = '" & Forms!frmaddll!txtlltr & "',[HN] = '" & Forms!frmaddll!txtllhull & "', [LL] = '" & Forms!frmaddll!txtll & "',[CA] = '" & Forms!frmaddll!txtllca & "',[CP] = '" & Forms!frmaddll!txtllcomponent & "',[LOC] = '" & Forms!frmaddll!txtllloc & "',[LFSE] = '" & Forms!frmaddll!txtlllfse & "',[FC] = '" & Forms!frmaddll!txtllfc & "' " & _
          "WHERE [LLN] = '" & Forms!frmaddll!txtlln.Value & "';"

    Replace (SQL, "'", "''")

    DoCmd.RunSQL SQL
    DoCmd.Requery

    Me.Refresh

End Sub

【讨论】:

  • 我只提供了他的示例。另外,我建议他选择参数。 @弗雷杜
  • 如果我按照你的方式直接输入代码 (SQL=SQL.replace...),它会收到一个错误,说无效限定并突出显示 SQL.replace 的 SQL 部分。如果我从替换中删除 SQL,则会收到更新的语法错误。
  • @Kewl147 立即尝试
  • VBA 和 SQL 在我可以使用的时候按顺序排列。
  • 收到语法错误,我尝试将其设置为单独的字符串并作为初始代码行之前的前言。有一次我设置它时说我有一个无效的运算符 = 。我还在重新安排。
猜你喜欢
  • 1970-01-01
  • 2019-10-09
  • 2011-06-19
  • 1970-01-01
  • 2020-04-19
  • 1970-01-01
  • 2010-09-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多