Building SQL strings in Access/VBA Building SQL strings in Access/VBA vba vba

Building SQL strings in Access/VBA


I have a timesheet app with a reasonably complex unbound labour transaction entry form. There is a lot of data validation, rate calculation and other code. I decided to use the following to create my SQL Insert/Update fields.

The variables strSQLInsert, strSQLValues, strSQLUpdate are form level strings.

Many lines of the following:

Call CreateSQLString("[transJobCategoryBillingTypesID]", lngJobCategoryBillingTypesID)

followed by:

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 Ifconn.Openconn.Execute strSQL, lngRecordsAffected, adCmdText

Note that the Mid lines remove the leading ", ". lngTrans is the value of the 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 SubtagError:    MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure CreateSQLString of VBA Document Form_LabourEntry"    Exit SubEnd Sub

I see that the other posters are all using the Execute method. The problem with DoCmd.RunSQL is that it can ignore errors. Either of the following will display any error messages received by the query. If using DAO, use Currentdb.Execute strSQL,dbfailonerror.. For ADO use CurrentProject.Connection.Execute strCommand, lngRecordsAffected, adCmdText You can then remove the docmd.setwarnings lines.

If you're going to use docmd.setwarnings make very sure you put the True statement in any error handling code as well. Otherwise weird things may happen later on especially while you are working on the app. For example you will no longer get the "Do you wish to save your changes" message if you close an object. This may mean that unwanted changes, deletions or additions will be saved to your MDB.

Also performance can be significantly different between the two methods. One posting stated currentdb.execute took two seconds while docmd.runsql took eight seconds. As always YMMV.


Adding to what @astander has said, you could create a querydef (with parameters) and save it as part of the database.

e.g.

Parameters dtBegin DateTime, dtEnd DateTime;INSERT into myTable (datebegin, dateend) values (dtBegin, dtEnd)

Assume, you saved it with a name myTableInsert, you could write the code as below

dim qd as QueryDefset qd = CurrentDB.QueryDefs("myTableInsert")qd.Parameters("dtBegin").Value = myTextFieldHavingBeginDateqd.Parameters("dtEnd").Value = myTextFieldHavingEndDate    qd.Execute

Note: I have not tested this piece of code. But, I am guessing this should be it.
Hope this gives you enough info to get started.


    Private Sub Command0_Click()Dim rec As Recordset2Dim sql As StringDim queryD As QueryDef    'create a temp query def.    Set queryD = CurrentDb.CreateQueryDef("", "SELECT * FROM [Table] WHERE Val = @Val")    'set param vals    queryD.Parameters("@Val").Value = "T"    'execute query def    Set rec = queryD.OpenRecordsetEnd Sub