VBA, ADO.Connection and query parameters VBA, ADO.Connection and query parameters vba vba

VBA, ADO.Connection and query parameters


You need to use an ADODB.Command object that you can add parameters to. Here's basically what that looks like

Sub adotest()    Dim Cn As ADODB.Connection    Dim Cm As ADODB.Command    Dim Pm As ADODB.Parameter    Dim Rs as ADODB.Recordset    Set Cn = New ADODB.Connection    Cn.Open "mystring"    Set Cm = New ADODB.Command    With Cm        .ActiveConnection = Cn        .CommandText = "SELECT * FROM table WHERE parentid=?;"        .CommandType = adCmdText        Set Pm = .CreateParameter("parentid", adNumeric, adParamInput)        Pm.Value = 1        .Parameters.Append Pm        Set Rs = .Execute    End WithEnd Sub

The question mark in the CommandText is the placeholder for the parameter. I believe, but I'm not positive, that the order you Append parameters must match the order of the questions marks (when you have more than one). Don't be fooled that the parameter is named "parentid" because I don't think ADO cares about the name other than for identification.


Alternative example returning a command from a function:

Function BuildCommand(conn As ADODB.Connection) As ADODB.Command    Dim cmd As ADODB.Command    Set cmd = New ADODB.Command    cmd.ActiveConnection = conn    cmd.CommandType = adCmdText    cmd.Parameters.Append cmd.CreateParameter("@name", adVarChar, adParamInput, 255, "Dave")    cmd.CommandText = "SELECT * FROM users WHERE name = @name;"    Set BuildCommand = cmdEnd Function

A couple things to note:

  1. When using adVarChar data type, the size argument to cmd.CreateParameter (e.g. 255) is required. Not supplying it results a run-time error 3708: Application-defined or object-defined error, as indicated in the documentation:

    If you specify a variable-length data type in the Type argument, you must either pass a Size argument or set the Size property of the Parameter object before appending it to the Parameters collection; otherwise, an error occurs.

  2. If the cmd.ActiveConnection property is set when cmd.CommandText is set, and cmd.CommandText contains named parameters, cmd.Parameters will be populated accordingly. Calling cmd.Parameters.Append afterwards could result in duplicates. For example:

    cmd.ActiveConnection = conncmd.CommandType = adCmdTextDebug.Print cmd.Parameters.Count ' 0cmd.CommandText = "SELECT * FROM users WHERE name = @name;"Debug.Print cmd.Parameters.Count ' 1cmd.Parameters.Append cmd.CreateParameter("@name", adVarChar, adParamInput, 255, "Dave")Debug.Print cmd.Parameters.Count ' 2

    I believe this is what is meant in the documentation, which is slightly inaccurate:

    If the Prepared property of the Command object is set to True and the Command object is bound to an open connection when you set the CommandText property, ADO prepares the query (that is, a compiled form of the query that is stored by the provider) when you call the Execute or Open methods.

    As a workaround, either set cmd.CommandText or cmd.ActiveConnection after adding parameters.