Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Issue running SQL Stored procedures via ADO 2

Status
Not open for further replies.

jrbarnett

Programmer
Jul 20, 2001
9,645
GB
I've written a stored procedure in T-SQL for the Northwind SQL Server sample database using the technique demonstrated at The code is as follows:

Code:
CREATE PROCEDURE dbo.ps_Customers_SELECT_CustomerDetails
@Contact_Name varchar(30) = NULL,
@Company_Name varchar(30) = NULL,
@City_Name varchar(30) = NULL,
@Country_Name varchar(30) = NULL
AS
SELECT Customers.CompanyName,
       Customers.ContactName,
       Customers.ContactTitle,
       Customers.Address,
       Customers.City,
       Customers.PostalCode,
       Customers.Country
FROM Customers
WHERE Customers.ContactName = COALESCE(@Contact_Name,Customers.ContactName) AND
      Customers.CompanyName = COALESCE(@Company_Name,Customers.CompanyName) AND
      Customers.City = COALESCE (@City_Name, Customers.City) AND
      Customers.Country = COALESCE(@Country_Name,Customers.Country)

When run from Query Analyser, I can use named parameters to specify whatever criteria I want, leave the others out and it returns the appropriate data. So far so good.

I went over to Access, created a new form and wrote some VBA ADO code to connect to SQL Server and retrieve the data.
With no parameters it worked great, retrieving all data.
When I specified one parameter which was not the first one, no data was retrieved.

By using SQL Profiler to monitor this connection, I found out that the code it submitted to the server doesn't specify the parameter name, and this is why it was failing.

For example, if I chose London as the city, I would expect it to submit something like
EXEC ps_Customers_SELECT_CustomerDetails @City_Name='London';

but it was submitting
EXEC ps_Customers_SELECT_CustomerDetails 'London'
- so it was trying to match a contact name against a city name, no wonder there was no data returned.

I can get around this by including null values for the parameters not required as follows (this is my completed code for the moment):

Code:
Private Sub cmdViewData_Click()
    ' Variables for database connection    
    Dim cnn As New ADODB.Connection
    Dim rs As New ADODB.Recordset
    Dim cmd As New ADODB.Command
    
    On Error GoTo err_cmdViewData_Click
    
    ' Connect to the database
    cnn.Open strDBConnect
    cnn.CursorLocation = adUseClient
    
    ' Set up the command object
    With cmd
        .ActiveConnection = cnn
        .CommandType = adCmdStoredProc
        .CommandText = "ps_Customers_SELECT_CustomerDetails"
        
        If Len(Me.txtContactName & "") > 0 Then
            .Parameters.Append .CreateParameter("Contact_Name", adVarChar, adParamInput, 30, Me.txtContactName)
        Else
            .Parameters.Append .CreateParameter("Contact_Name", adVarChar, adParamInput, 30, Null)
        End If
        
        If Len(Me.txtCompanyName & "") > 0 Then
            .Parameters.Append .CreateParameter("Company_Name", adVarChar, adParamInput, 30, Me.txtCompanyName)
        Else
            .Parameters.Append .CreateParameter("Company_Name", adVarChar, adParamInput, 30, Null)
        End If
        
        If Len(Me.txtCity & "") > 0 Then
            .Parameters.Append .CreateParameter("City_Name", adVarChar, adParamInput, 30, Me.txtCity)
        Else
            .Parameters.Append .CreateParameter("City_Name", adVarChar, adParamInput, 30, Null)
        End If
        
        If (Me.cboCountry & "") > 0 Then
            .Parameters.Append .CreateParameter("Country_Name", adVarChar, adParamInput, 30, Me.cboCountry)
        Else
            .Parameters.Append .CreateParameter("Country_Name", adVarChar, adParamInput, 30, Null)
        End If
        Set rs = .Execute
    End With
    
    Set Me.Recordset = rs
    Me.txtContactName.ControlSource = "ContactName"
    Me.txtCompanyName.ControlSource = "CompanyName"
    Me.cboCountry.ControlSource = "Country"
    Me.txtContactTitle.ControlSource = "ContactTitle"
    Me.txtPostcode.ControlSource = "Postalcode"
    Me.txtCity.ControlSource = "City"
    Me.txtAddress.ControlSource = "Address"
    
    DoCmd.OpenForm Me.Name, acFormDS ' Switch to Datasheet view to see data in a list format.

Exit_cmdViewData_Click:
    If Not (cnn Is Nothing) Then cnn.Close
    Exit Sub
    
err_cmdViewData_Click:
    MsgBox Err.Number & ": " & Err.Description
    Resume Next
    
End Sub

Platforms in use in my test environment:
* SQL Server 2000 SP4 Developer Edition
* Windows 2000 Professional SP4
* Access XP SP3
* Reference to ActiveX Data Objects 2.8 Library in Access.

Questions:
1. Why does ADO not pass across the parameter name as mentioned above? Can I force it to pass it across?

2. Does anybody have any comments regarding this code?

I'm new to running SQL code from Access, and am likely to need to upsize a fair number of systems soon and rewrite the frontends for optimal operation in both Access and Excel.
I'd like to get any bad habits out of the way before they get too ingrained in my head.

John
 
Code:
    With cmd
        .ActiveConnection = cnn
        .CommandType = adCmdStoredProc
        .CommandText = "ps_Customers_SELECT_CustomerDetails"
        .Parameters.Refresh
        If Len(Me.txtContactName & "") > 0 Then
           .Parameters("Contact_Name")= Me.txtContactName
        Else
           .Parameters("Contact_Name")= Null
        End If
        If Len(Me.txtCompanyName & "") > 0 Then
           .Parameters("Company_Name") = Me.txtCompanyName
        Else
            .Parameters("Company_Name") = Null
        End If
        If Len(Me.txtCity & "") > 0 Then
           .Parameters("City_Name") = Me.txtCity
        Else
           .Parameters("City_Name") = Null
        End If
        If (Me.cboCountry & "") > 0 Then
           .Parameters("Country_Name") = Me.cboCountry
        Else
           .Parameters("Country_Name") = Null
        End If
        Set rs = .Execute
    End With
End Sub
 
Hi Jerry

Thanks for that code. I've just given it a try, commenting my own out (from With through to End with).

It doesn't work - my error handler gets triggered at every .Parameters("ParameterName") = Me.txtControlName

line, throwing error 3265 (Item cannot be found in the collection corresponding to the requested name or ordinal) for every parameter, regardless of whether selection criteria has been entered for that field.
It still executes the procedure though, and always returns all data.

Any ideas?

John
 
You might need quotes. try this
Code:
    With cmd
        .ActiveConnection = cnn
        .CommandType = adCmdStoredProc
        .CommandText = "ps_Customers_SELECT_CustomerDetails"
        .Parameters.Refresh
        If Len(Me.txtContactName & "") > 0 Then
           .Parameters("Contact_Name")= "'" & Trim(Me.txtContactName) & "'"
        Else
           .Parameters("Contact_Name")= Null
        End If
        If Len(Me.txtCompanyName & "") > 0 Then
           .Parameters("Company_Name") = "'" & Trim(Me.txtCompanyName) & "'"
        Else
            .Parameters("Company_Name") = Null
        End If
        If Len(Me.txtCity & "") > 0 Then
           .Parameters("City_Name") = "'" & Trim(Me.txtCity) & "'"
        Else
           .Parameters("City_Name") = Null
        End If
        If (Me.cboCountry & "") > 0 Then
           .Parameters("Country_Name") = "'" & Trim(Me.cboCountry) & "'"
        Else
           .Parameters("Country_Name") = Null
        End If
        Set rs = .Execute
    End With
End Sub
 
And what about this ?
...
.CommandText = "ps_Customers_SELECT_CustomerDetails"
.Parameters.Append .CreateParameter("Contact_Name", adVarChar, adParamInput, 30, _
IIf(Trim(Me!txtContactName & "") = "", Null, Me!txtContactName))
.Parameters.Append .CreateParameter("Company_Name", adVarChar, adParamInput, 30, _
IIf(Trim(Me!txtCompanyName & "") = "", Null, Me!txtCompanyName))
...

Hope This Helps, PH.
Want to get great answers to your Tek-Tips questions? Have a look at FAQ219-2884 or FAQ181-2886
 
Jerry and PHV - Thank you for your code - they both work, provided I don't have the .Parameters.Refresh line in the code. As soon as I put it in, the code stops working.

This turned out to be my mistake - Access was wanting the SQL parameters names with the @ symbol before the parameter name.

With regards to specifying names of parameters, you have to set the .NamedParameters option of the ADODB.Command object to True before executing it.
Thus, I can take out the code for putting null values in unspecified parameters, greatly simplifying it. The final code is:

Code:
Private Sub cmdViewData_Click()
    ' Variables for database connection    
    Dim cnn As New ADODB.Connection
    Dim rs As New ADODB.Recordset
    Dim cmd As New ADODB.Command
    
    On Error GoTo err_cmdViewData_Click
    
    ' Connect to the database
    cnn.Open strDBConnect
    cnn.CursorLocation = adUseClient
    
    ' Set up the command object
    With cmd
        .ActiveConnection = cnn
        .CommandType = adCmdStoredProc
        .CommandText = "ps_Customers_SELECT_CustomerDetails"
        .NamedParameters = True
        
        If Len(Me.txtContactName & "") > 0 Then
             .Parameters("@Contact_Name").Value =               Me.txtContactName        
        End If
        
        If Len(Me.txtCompanyName & "") > 0 Then
             .Parameters("@Company_Name") = Me.txtCompanyName
        End If
        
        If Len(Me.txtCity & "") > 0 Then
            .Parameters("@City_Name").Value = Me.txtCity     
        End If
        
        If (Me.cboCountry & "") > 0 Then
           .Parameters("@Country_Name").Value = Me.cboCountry
        End If

        Set rs = .Execute
    End With
    
    Set Me.Recordset = rs
    Me.txtContactName.ControlSource = "ContactName"
    Me.txtCompanyName.ControlSource = "CompanyName"
    Me.cboCountry.ControlSource = "Country"
    Me.txtContactTitle.ControlSource = "ContactTitle"
    Me.txtPostcode.ControlSource = "Postalcode"
    Me.txtCity.ControlSource = "City"
    Me.txtAddress.ControlSource = "Address"
    
    DoCmd.OpenForm Me.Name, acFormDS ' Switch to Datasheet view to see data in a list format.

Exit_cmdViewData_Click:
    If Not (cnn Is Nothing) Then cnn.Close
    Exit Sub
    
err_cmdViewData_Click:
    MsgBox Err.Number & ": " & Err.Description
    Resume Next
    
End Sub

Thank you very much everybody for your help. I've learned a lot doing this and it will probably be used as early as next week in test systems.

John

 
hmm, interesting...

currently I'm using the same method as PHV, but with jr's way there's less code to type...

is anyone aware of any good reason not to do it like jr?

--------------------
Procrastinate Now!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top