在Access/VBA中构建SQL字符串

Dal*_*ale 15 sql ms-access vba

偶尔,我不得不在VBA中构建一个SQL字符串并使用它来执行它Docmd.RunSql().我总是通过将变量连接到字符串中来构建这些字符串,例如:

Dim mysqlstring as String
mysqlstring = "INSERT INTO MyTable (Field1, Field2, Field3 ...) VALUES ("
mysqlstring = mysqlstring + Me.TextMyField1 + ", " 'parameter comments
mysqlstring = mysqlstring + Me.TextMyField2 + ", " 
mysqlstring = mysqlstring + Me.TextMyField3 + ", " 
...
mysqlstring = mysqlstring + ");"
Docmd.RunSql mysqlstring
Run Code Online (Sandbox Code Playgroud)

VBA似乎没有一元连接运算符(如+ =),虽然这看起来并不理想,但至少我可以评论每个参数并单独更改它们.它比一个怪物串联字符串更容易阅读和更改.但它似乎仍然是一种构建SQL字符串的可怕方法.我有一个约50个参数在工作,所以50行mysqlstring = mysqlstring +....不可爱.

顺便提一下,这排除了使用行继续来格式化字符串,因为对单个字符串可以使用的行继续数限制(提示:小于50).此外,VBA不会让你在续行后发表评论,grr!

直到最近,我认为这是构建这些字符串的唯一方法.但是最近我看到了一个不同的模式,在这个问题(VB.NET)的字符串中注入参数我发布了答案,并想知道是否有相当于Parameters.AddWithValue()VBA,或者如果这甚至比任何更好字符串连接方法.所以我认为这值得提出自己的问题.也许我在这里缺少一些东西.

一些Access专家可以澄清在Access/VBA中构建SQL字符串的最佳实践.

Ton*_*ews 9

我有一个时间表应用程序,具有相当复杂的非绑定人工交易输入表单.有很多数据验证,速率计算和其他代码.我决定使用以下内容来创建SQL插入/更新字段.

变量strSQLInsert,strSQLValues,strSQLUpdate是表单级别的字符串.

以下许多行:

Call CreateSQLString("[transJobCategoryBillingTypesID]", lngJobCategoryBillingTypesID)
Run Code Online (Sandbox Code Playgroud)

其次是:

If lngTransID = 0 Then
    strSQL = "INSERT into Transactions (" & Mid(strSQLInsert, 3) & ") VALUES (" & Mid(strSQLValues, 3) & ")"
Else
    strSQL = "UPDATE Transactions SET " & Mid(strSQLUpdate, 3) & " WHERE transID=" & lngTransID & ";"
End If

conn.Open
conn.Execute strSQL, lngRecordsAffected, adCmdText
Run Code Online (Sandbox Code Playgroud)

请注意,Mid行会删除前导",".lngTrans是autonumber primamy kay的值.

Sub CreateSQLString(strFieldName As String, varFieldValue As Variant, Optional blnZeroAsNull As Boolean)
'    Call CreateSQLString("[<fieldName>]", <fieldValue>)

Dim strFieldValue As String, OutputValue As Variant

    On Error GoTo tagError

    ' if 0 (zero) is supposed to be null
    If Not IsMissing(blnZeroAsNull) And blnZeroAsNull = True And varFieldValue = 0 Then
        OutputValue = "Null"
    ' if field is null, zero length or ''
    ElseIf IsNull(varFieldValue) Or Len(varFieldValue) = 0 Or varFieldValue = "''" Then
        OutputValue = "Null"
    Else
        OutputValue = varFieldValue
    End If

    ' Note that both Insert and update strings are updated as we may need the insert logic for inserting
    '    missing auto generated transactions when updating the main transaction
    ' This is an insert
    strSQLInsert = strSQLInsert & ", " & strFieldName
    strSQLValues = strSQLValues & ", " & OutputValue
    ' This is an update
    strSQLUpdate = strSQLUpdate & ", " & strFieldName & " = " & OutputValue

    On Error GoTo 0
    Exit Sub

tagError:

    MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure CreateSQLString of VBA Document Form_LabourEntry"
    Exit Sub
End Sub
Run Code Online (Sandbox Code Playgroud)

我看到其他海报都使用了Execute方法.DoCmd.RunSQL的问题在于它可以忽略错误.以下任一项都将显示查询收到的任何错误消息.如果使用DAO,请使用Currentdb.Execute strSQL,dbfailonerror ..对于ADO,请使用CurrentProject.Connection.Execute strCommand,lngRecordsAffected,adCmdText然后可以删除docmd.setwarnings行.

如果您打算使用docmd.setwarnings,请确保将True语句放在任何错误处理代码中.否则可能会在以后发生奇怪的事情,特别是在您使用该应用程序时.例如,如果关闭对象,则不会再显示"是否要保存更改"消息.这可能意味着不需要的更改,删除或添加将保存到您的MDB.

两种方法之间的性能也可能有很大差异.一篇帖子称currentdb.execute花了两秒钟,而docmd.runsql花了八秒钟.YMMV一如既往.