使用VBA添加新记录

时间:2015-08-12 20:50:55

标签: sql vba ms-access access-vba

我有一个表单,其中一个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查询更好的情况下,我该怎么做才能执行它?

2 个答案:

答案 0 :(得分:2)

您在插入记录时询问哪个更好:使用发布到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语句旨在处理行块。仅使用IifChoose或{{更难表达每行逻辑3}}功能;并且使用纯SQL更难或不可能依赖于当前状态(例如Switch)的逻辑。这可以使用Recordset方法方法轻松完成。

    如果您具有在模块级变量中保持状态的函数,则也可以使用VBA和SQL的组合启用此功能。需要注意的是:每次发出SQL语句之前,您都需要重置状态。有关示例,请参阅insert every other record

答案 1 :(得分:1)

您的问题的一部分 * 询问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无声地失败。 (对我来说,那绝不是。)