Category Archives: 13045

SUMPRODUCT Isn’t The Only SP Kid In Town


If you are
a frequent use of SQL Server, or any such enterprise database solution, you are
bound to be aware of Stored Procedures (SPs) and the advantages that they
bring. In my experience, using SPs is almost de-facto in the SQL
Server world.

 

However, it
does not seem so prevalent in the Access databases and applications that I have
seen. Presumably, this is because Access applications are very closely bound to
the Access database, and the rationale drops off somewhat. But I never use the
Access UI myself, although I have created many applications where Access is my
database with Excel serving as the client interface. In these applications, I
communicate with the database using ActiveX
Data Objects (ADO)
.

 

When I
first started using Access databases, I could not see how to create SPs in
Access, indeed as I recall, it was not
initially possible. This meant that I
had a ton of SQL code in my applications for communicating with the database,
which is not where in belongs according to my design principles. There are queries in Access
that can be called, but as I said, I don’t use the Access UI, and I also want
to pass parameters to my SP.

 

Access does
now support SPs. I am not sure from which version, but it is certainly true
form Access 2003 onwards.

 

Suppose we
had a simple database list that we wanted to use in a SP, SQL that looks like
this

 

SELECT   RU.LoginID,
         RU.UserName,
         RU.Supervisor,
         RU.UserReports,
         RU.Salesman,
         RU.Deleted
FROM   refUsers AS RU
ORDER BY RU.UserName ASC;”

 

Assuming
this SP is called spListUsers, the Excel code to bring this list back to a Recordset
would be

 

Dim
mpConnection As Object
Dim mpCommand As Object
Dim mpRS As ObjectDim mpConnection As Object
Dim mpCommand As Object
Dim mpRS As Object

    Set mpConnection =
CreateObject(“ADODB.Connection”)
    mpConnection.Open =
“Provider=Microsoft.Jet.OLEDB.4.0;” & _
                        “Data
Source=” & mcDatabase

    Set mpCommand =
CreateObject(“ADODB.Command”)
    Set mpCommand.ActiveConnection =
mpConnection
    mpCommand.CommandText =
“spListUsers”
    mpCommand.CommandType =
adCmdStoredProc

    Set mpRS =
CreateObject(“ADODB.Recordset”)
    mpRS.Open mpCommand

 

And the great thing is that it is
possible to create these SPs from within Excel using ADO. All that is needed is this code

 

Dim
mpConnection As Object
Dim mpCommand As Object

    Set mpConnection =
CreateObject(“ADODB.Connection”)
    mpConnection.Open =
“Provider=Microsoft.Jet.OLEDB.4.0;” & _
                        “Data
Source=” & mcDatabase

    On Error Resume Next
        mpConnection.Execute “DROP
PROCEDURE spListUsers”
    On Error GoTo 0
    mpConnection.Execute “CREATE
PROCEDURE spListUsers ” & _
            “AS “ & _
            “SELECT RU.LoginID, “ & _
                  RU.UserName, “ & _
                  
RD.DesignerID, “ & _
                  
RU.Supervisor, “ & __
                   RU.UserReports, “ & _
                   RU.Salesman, “ & _
               
   RU.Deleted “ & _
            “FROM   refUsers AS RU “ & _
            “ORDER BY RU.UserName ASC;”

 

Introducing
parameters adds a certain level of complexity, but nothing too troublesome. The parameter has
to be declared in the code to create the SP, and it has to be passed when
executing the SP.

 

Creating an
SP, spGetUser
in this example, with a text parameter called prmUserName, would look
something like this

 

Dim
mpConnection As Object
Dim mpCommand As Object

    Set mpConnection =
CreateObject(“ADODB.Connection”)
    mpConnection.Open =
“Provider=Microsoft.Jet.OLEDB.4.0;” & _
                        “Data
Source=” & mcDatabase

    On Error Resume Next
        mpConnection.Execute “DROP
PROCEDURE spGetUser
   
On Error GoTo 0


    
mpConnection.Execute “CREATE PROCEDURE spGetUser “ & _
        “(prmUserName Varchar (50)) “
& _
        “AS “ & _
        “SELECT RU.LoginID, “ & _
       
      RU.UserName, “ & _
               RD.DesignerID,
“ & _
               RU.Supervisor,
“ & __
               RU.UserReports, “ & _
               RU.Salesman, “ & _
               RU.Deleted , “ & _
               RU.UpdatedBy, “ & _
               RU.UpdatedOn “ & _
        “FROM   refUsers AS RU“ & _
               LEFT
JOIN refDesigners AS RD“ & _
               ON
RU.LoginID = RD.LoginID“ & _
        “WHERE  RU.UserName = prmUserName;”

 

And calling
it would look like this

 

Dim
mpConnection As Object
Dim mpCommand As Object
Dim mpParameter As Object
Dim mpRS As Object

    Set mpConnection =
CreateObject(“ADODB.Connection”)
    mpConnection.Open =
“Provider=Microsoft.Jet.OLEDB.4.0;” & _
                        “Data
Source=” & mcDatabase

    Set mpCommand =
CreateObject(“ADODB.Command”)
    mpCommand.ActiveConnection =
mpConnection

    mpCommand.CommandText = “spGetUser”
    mpCommand.CommandType =
adCmdStoredProc

    Set mpParameter =
mpCommand.CreateParameter(“prmUserName”, _
                                               
adVarChar, _
                                               
adParamInput, _
                                                Len(“Bob
Phillips”)) ‘the parameter value
    mpParameter.Value = “Bob
Phillips”
    mpCommand.Parameters.Append
mpParameter

    Set mpRS =
CreateObject(“ADODB.Recordset”)
    mpRS.Open mpCommand

 

If your SP
requires multiple parameters, each parameter is defined separately, loaded and appended
as in the single example above.

 

Clearly,
your SPs are likely to be more complex than these trivial examples, but the
principle holds out with more complex SPs.

 

So there
you have it, you can remove all of the inline SQL from your applications,
create a separate SP creator app that creates the SPs, have better structured
code, and more maintainable. Does it get any better than that?