我有一个表单,其中一个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查询更好的情况下,我该怎么做才能执行它?
答案 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语句有其局限性:
这在Access中得到了部分缓解,因为SQL语句可以使用您定义的许多VBA built-in functions或函数。
SQL语句旨在处理行块。仅使用Iif,Choose或{{更难表达每行逻辑3}}功能;并且使用纯SQL更难或不可能依赖于当前状态(例如Switch)的逻辑。这可以使用Recordset方法方法轻松完成。
如果您具有在模块级变量中保持状态的函数,则也可以使用VBA和SQL的组合启用此功能。需要注意的是:每次发出SQL语句之前,您都需要重置状态。有关示例,请参阅insert every other record。
答案 1 :(得分:1)
您的问题的一部分 * 询问INSERT
与Recordset.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
无声地失败。 (对我来说,那绝不是。)