【问题标题】:Adding a new record with VBA使用 VBA 添加新记录
【发布时间】:2015-08-17 16:05:27
【问题描述】:

我有一个表单,其中一个 ComboBoxes 列出了给定项目的所有文档。用户应该选择一个,然后按下一个按钮,如果在表Dessins中出现,它会打开显示该记录的第二个表单。如果该表中不存在,我想添加它。

我的一位同事告诉我,我所要做的就是使用 VBA 执行 SQL 查询。我到目前为止是这样的:

    Dim rsDessin As DAO.Recordset
    Dim strContrat As String
    Dim strProjet As String
    Dim strDessin As String
    Dim sqlquery As String

  'I think these next 3 lines are unimportant. I set a first query to get information I need from another table

    strDessin = Me.Combo_Dessin
    strProjet = Me.Combo_Projet
    sqlquery = "SELECT [Projet HNA] FROM [Projets] WHERE [Projet AHNS] = '" & strProjet & "'"

    Set rsDessin = CurrentDb.OpenRecordset(sqlquery)

    If Not rsDessin.RecordCount > 0 Then 'If not present I want to add it 
        strContrat = rsDessin![Projet HNA]
        sqlquery = "INSERT INTO Feuilles ([AHNS], [Contrat], [No Projet]) VALUES (strDessin, strContrat, strDessin)"
        'Not sure what to do with this query or how to make sure it worked.
    End If

 'Checking my variables
    Debug.Print strProjet
    Debug.Print strContrat
    Debug.Print strDessin

 'By here I'd like to have inserted my new record.

    rsDessin.Close
    Set rsDessin = Nothing

我也在网上读到,我可以通过以下方式获得类似的结果:

Set R = CurrentDb.OpenRecordset("SELECT * FROM [Dessins]")
R.AddNew
R![Contrat] = strContrat
R![Projet] = strProjet
R![AHNS] = strDessin
R.Update
R.Close
Set R = Nothing
DoCmd.Close

一种方法比另一种更好吗?在我的 INSERT INTO 查询更好的情况下,我应该怎么做才能执行它?

【问题讨论】:

  • 你说得对,这不是我想要的。我已经修好了,谢谢指出!
  • 你也应该直接停止使用CurrentDb。创建一个变量Set db=CurrentDb 并改用db

标签: sql ms-access vba


【解决方案1】:

您问的是插入记录时哪个更可取:使用发出给Database 对象的SQL 语句,或使用Recordset 对象的方法。

对于单个记录,没关系。但是,您可以像这样发出INSERT 语句:

CurrentDb.Execute "INSERT INTO Feuilles ([AHNS], [Contrat], [No Projet]) VALUES (" & strDessin & ", " & strContrat & ", " & strDessin & ")", dbFailOnError

(您应该使用 dbFailOnError 选项来捕获某些错误,正如 HansUp 在 this answer 中指出的那样。)


对于从另一个表或查询中插入多条记录,发出这样的 SQL 语句通常更快更有效:

Dim sql = _
    "INSERT INTO DestinationTable (Field1, Field2, Field3) " & _
    "SELECT Field1, Field2, Field3 " & _
    "FROM SourceTable"
CurrentDb.Execute sql

比使用 Recordset 对象的等价物:

Dim rsSource As DAO.Recordset, rsDestination As DAO.Recordset
Set rsSource = CurrentDb.OpenRecordset("SourceTable")
Set rsDestination = CurrentDb.OpenRecordset("DestinationTable")
Do Until rs.EOF
    rsDestination.AddNew
    rsDestination!Field1 = rsSource!Field1
    rsDestination!Field2 = rsSource!Field2
    rsDestination!Field3 = rsSource!Field3
    rsDestination.Update
    rs.MoveNext
Loop

也就是说,使用 SQL 语句有其局限性:

  • 您仅限于SQL syntax and functions

    这在 Access 中得到了部分缓解,因为 SQL 语句可以使用许多 VBA built-in functions 或您定义的函数。

  • SQL 语句设计用于处理行块。 仅使用IifChooseSwitch 函数更难表达每行逻辑;并且依赖于当前状态的逻辑(例如insert every other record)使用纯 SQL 更难或不可能。这可以使用 Recordset 方法轻松完成。

    这也可以使用 VBA 和 SQL 的组合来启用,如果您有在模块级变量中保持状态的函数。一个警告:您需要在每次发出 SQL 语句之前重置状态。示例见here

【讨论】:

    【解决方案2】:

    您的问题的一部分* 询问了INSERTRecordset.AddNew 添加一行。我建议使用这种记录集方法:

    Dim db As DAO.Database
    Dim R As DAO.Recordset
    Set db = CurrentDb
    Set R = db.OpenRecordset("Dessins", dbOpenTable, dbAppendOnly)
    With R
        .AddNew
        !Contrat = rsDessin![Projet HNA].Value
        !Projet = Me.Combo_Projet.Value
        !AHNS = Me.Combo_Dessin.Value
        .Update
        .Close
    End With
    

    * 您还询问了如何执行INSERT。使用 Zev 推荐的 DAO.Database.Execute 方法并包含 dbFailOnError 选项。这将增加某些插入失败的清晰度。例如,密钥违规错误可能会使您的 INSERT 静默失败。但包含 dbFailOnError 可确保您立即收到有关问题的通知。因此,请始终包含该选项...除非您实际上希望允许 INSERT 静默失败。 (对我来说,从来没有。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-30
      • 1970-01-01
      • 1970-01-01
      • 2021-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多