VBA:为什么我的INSERT代码不起作用?

时间:2015-12-01 15:23:01

标签: vba insert

几周前我有这个工作,但现在我不确定我做了什么让它不再起作用了。我甚至没有收到错误消息,以找出可能出错的地方。当我单击我在表格中插入一行时,没有任何反应。表单被清除并且表被重新获取,但代码的INSERT部分没有做任何事情。

Public Sub Command125_Click()
    'Add row for downtime

    Dim dbsCurrent As Database
    Set dbsCurrent = CurrentDb

    dbsCurrent.Execute " INSERT INTO tbl_Downtime " _
    & "(job, suffix, production_date, reason, downtime_minutes, comment, shift) VALUES " _
    & "('" & Me.Text116 & "','" & Me.Text118 & "','" & Me.Text126 & "','" & Me.Text121 & "','" & Me.Text123 & "','" & Me.Text128 & "','" & Me.Text144 & "');"

   Call ClearControl(Me.Text116)
   Call ClearControl(Me.Text118)
   Call ClearControl(Me.Text126)
   Call ClearControl(Me.Text121)
   Call ClearControl(Me.Text123)
   Call ClearControl(Me.Text128)
   Call ClearControl(Me.Text144)

   Me.subrpt_DowntimeTable.Requery

End Sub

我正在尝试的代码基于@ Hambone的回答:

Public Sub Command125_Click()

Dim dbsCurrent As Database
Set dbsCurrent = CurrentDb

Dim query As QueryDef
    Dim sql As String

    For Each query In CurrentDb.QueryDefs
      If query.Name = "InsertDowntime" Then
        Exit For
      End If
    Next query

    If query Is Nothing Then
      sql = "parameters " & _
        "P1 text, P2 text, P3 Date, P4 Text, P5 Number, P6 Text, P7 Text;" & _
        "insert into [tbl_Downtime] " & _
        "(job, suffix, production_date, reason, downtime_minutes, comment, shift) " & _
        " VALUES ([P1], [P2], [P3], [P4], [P5], [P6], [P7])"

      Set query = CurrentDb.CreateQueryDef("InsertDowntime", sql)
    End If

    query.Parameters("P1").Value = "test1"
    query.Parameters("P2").Value = "test2"
    query.Parameters("P3").Value = Now()
    query.Parameters("P4").Value = "test3"
    query.Parameters("P5").Value = 15
    query.Parameters("P6").Value = "Miles O'Brien is a darn good transporter chief"
    query.Parameters("P7").Value = "test6"

    query.Execute

    MsgBox query.Parameters("P1").Value & query.Parameters("P2").Value & query.Parameters("P3").Value & query.Parameters("P4").Value & query.Parameters("P5").Value & query.Parameters("P6").Value & query.Parameters("P7").Value

    Me.subrpt_DowntimeTable.Requery

End Sub

3 个答案:

答案 0 :(得分:1)

我不会在Execute-Method中构建SQL语句。 创建变量并首先构建字符串。所以你可以调试实际值并单独测试它。

您还可以尝试使用选项dbFailOnError执行方法。

Dim stmt as String
stmt = "INSERT INTO....."
dbsCurrent.Execute stmt, dbFailOnError

使用不同的输入测试INSERT语句。普通用户在表单中输入的内容并不重要,但应用程序允许他执行此操作。如果未检查输入并且用户可以输入他/她想要的所有内容,那么查询可能会失败,产生奇怪的结果或 - 如上所述 - 允许SQL注入。最好的SQL注入是您作为开发人员永远不会注意到的。所以你会知道你有问题。

答案 1 :(得分:1)

MarkB和gmiley绝对正确使用参数。它前面的代码多一点,后来保存了无数个小时。而且,这是一个很好的做法。

也就是说,对于本机Access查询(不是ADO数据库查询),它不是世界上最直接的过程。在我看来,正常的ADO东西在你做了一两次后才开始有意义,但是对于Access查询,我仍然需要回过头来剽窃旧的例子才能使它工作。

在你的情况下,我认为这样的事情会起到作用:

  Dim query As QueryDef
  Dim sql As String

  For Each query In CurrentDb.QueryDefs
    If query.Name = "InsertDowntime" Then
      Exit For
    End If
  Next query

  If query Is Nothing Then
    sql = "parameters " & _
      "P1 text, P2 text, P3 Date, P4 Text, P5 Number, P6 Text, P7 Text;" & _
      "insert into [tbl_Downtime] " & _
      "(job, suffix, production_date, reason, downtime_minutes, comment, shift) " & _
      " VALUES ([P1], [P2], [P3], [P4], [P5], [P6], [P7])"

    Set query = CurrentDb.CreateQueryDef("InsertDowntime", sql)
  End If

  query.Parameters("P1").Value = "test1"
  query.Parameters("P2").Value = "test2"
  query.Parameters("P3").Value = Now()
  query.Parameters("P4").Value = "test3"
  query.Parameters("P5").Value = 15
  query.Parameters("P6").Value = "Miles O'Brien is a darn good transporter chief"
  query.Parameters("P7").Value = "test6"

  query.Execute

您从文本框中提取数据。我使用硬编码值来证明如果您的值不是所有文本,这也会管理数据输入。无需引用' text或#hash #date。您显然可以将这些更改回Me.TextBox123并更改数据类型以匹配tbl_Downtime中的实际字段。

- 编辑12/3/15 -

如果您已经在其中查询了此查询文字,那么For Each query In CurrentDb.QueryDefs之前query.Parameters之前的代码的整个部分可以理论上被忽略(如你进入Access,创建了一个查询,从设计视图转到SQL视图并输入并命名为InsertDowntime):

parameters
P1 text, P2 text, P3 Date, P4 Text, P5 Number, P6 Text, P7 Text;
insert into [tbl_Downtime]
(job, suffix, production_date, reason, downtime_minutes, comment, shift)
VALUES ([P1], [P2], [P3], [P4], [P5], [P6], [P7])

因为你不是,我只是通过代码创建了它。如果您尝试再次创建它,Access会因为InsertDowntime已经存在而呕吐。

无论哪种方式,一旦它存在,你可以管理它的方式是

Dim query As QueryDef
Set query = CurrentDb.QueryDefs("InsertDowntime")

然后其他所有应该就像我拥有它一样。

就个人而言,我会选择2 - 在Access中创建查询并将其保存为持久对象,并按照上面列出的方式访问它。我想我可以说,但是你的问题是VBA问题,而且我保留了VBA - 加上我认为动态创建查询的能力很酷。

答案 2 :(得分:0)

根据我们的讨论,您需要查看参数化查询:https://support.microsoft.com/en-us/kb/181734

主要原因是1)它将确保您的代码不会被有意或无意的SQL注入。由于无法始终在自由格式字段中控制用户输入,因此确保查询参数化使得无法执行任意代码; 2)可读性,当参数化值时,它使得读取代码变得容易得多。