sql - 在 Access/VBA 中构建 SQL 字符串

标签 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

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

顺便说一句,这排除了使用行继续来格式化字符串,因为有一个 limit on the number of line-continuations you can use on a single string (提示:小于 50)。此外,VBA 不允许您在续行之后添加注释,grr!

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

一些 Access 专家能否澄清在 Access/VBA 中构建 SQL 字符串的最佳实践。

最佳答案

我有一个时间表应用程序,其中包含相当复杂的非绑定(bind)劳动力交易输入表。里面有很多数据验证、费率计算等代码。我决定使用以下内容来创建我的 SQL 插入/更新字段。

变量 strSQLInsert、strSQLValues、strSQLUpdate 是表单级字符串。

以下多行:

Call CreateSQLString("[transJobCategoryBillingTypesID]", lngJobCategoryBillingTypesID)

其次是:
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

请注意,中间线删除了前导“,”。 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

我看到其他海报都在使用 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。

关于sql - 在 Access/VBA 中构建 SQL 字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1802120/

相关文章:

sql - JPA 按所选列获取结果列表顺序

sql - 根据别名增量值连接两个 SQL 表

excel - 将工作簿另存为 *.xml 到子文件夹时的目录问题

c# - 使用 C# 将一个 Access 数据库复制到另一个数据库

ms-access - 无法在 MS Access 中的 "Form"对象上使用 "SubForm"属性?

xml - 从 Access 中导出嵌套的 XML 文件。需要带有节点的 XML 文件

c# - 通过 C#(VSTO)/VBA 访问 Excel 2010 公式编辑器

sql - 如何向 Azure SQL 数据库中的用户授予数据库范围凭据

sql - 奇怪的 Oracle 行为 : TO_DATE and CONCAT in WHERE clause

ms-access - 除非您将鼠标移到某个控件上,否则 Access 不会停止 "Calculating . . . "