SQL Server Stored Procedure doesnt appear to be called - sql-server

The syntax of my code in MS Access appears to be correct.
I can run the stored procedure manually in SQL and get the correct result.
When I try to call the stored procedure from MS Access using ADO nothing appears to happen; any help would be greatly appreciated.
Private Sub Combo13_LostFocus()
Dim P1 As Integer
P1 = Forms![Frm_Ws10a]![Frm_WS10b]![Combo13].Column(0)
Dim rs As ADODB.Recordset
Dim CN As ADODB.Connection
Dim cmd As ADODB.Command
Dim prm As ADODB.Parameter
Dim adstring As Variant
Set CN = New ADODB.Connection
CN.ConnectionString = "Driver=SQL
Server;Server=LDXFBHD013492 \SQLEXPRESS;Database=xxxx;Trusted_Connection=YES;"
CN.Open
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = CN
.CommandText = "dbo.usp_update_consequenceweighting"
.CommandType = adCmdStoredProc
.Parameters.Refresh
Set prm = .CreateParameter("#ITID", adInteger, adParamInput)
prm.Value = P1
End With
Set rs = cmd.Execute
Me.Recalc
Me.Refresh
Thanks in advance

You are missing the .parameters.append in your code below
With cmd
.ActiveConnection = CN
.CommandText = "dbo.usp_update_consequenceweighting"
.CommandType = adCmdStoredProc
.Parameters.Refresh
Set prm = .CreateParameter("#ITID", adInteger, adParamInput)
Try adding the parameter.append instead of setting it
With cmd
.ActiveConnection = CN
.CommandText = "dbo.usp_update_consequenceweighting"
.CommandType = adCmdStoredProc
.parameter.append .createparameter("#ITID", adInteger, adParamInput, 50, [Value or variable here])
.execute 1
End With

Related

Run SQL Server stored procedure from VBA

This is my stored procedure which works fine in SQL Server Management Studio.
exec GroupCommissions #GroupNumberEntry = '01142'
Should produce a table of data.
I'm trying to run it in vba using the following code:
Dim rs As ADODB.Recordset
Dim cnSQL As ADODB.Connection
Dim sqlcommand As ADODB.Command, prm As Object
Set cnSQL = New ADODB.Connection
cnSQL.Open "Provider=SQLOLEDB; Data Source=bddc1didw1;Initial Catalog=Actuarial; Trusted_connection=Yes; Integrated Security='SSPI'"
Set sqlcommand = New ADODB.Command
sqlcommand.ActiveConnection = cnSQL
sqlcommand.CommandType = adCmdStoredProc
sqlcommand.CommandText = "GroupCommissions"
Set prm = sqlcommand.CreateParameter("GroupNumberEntry", adParamInput)
sqlcommand.Parameters.Append prm
sqlcommand.Parameters("GroupNumberEntry").Value = "01142"
Set rs = New ADODB.Recordset
rs.CursorType = adOpenStatic
rs.LockType = adLockOptimistic
rs.Open sqlcommand
ActiveSheet.Range("a3").CopyFromRecordset rs
But it just returns blank and I can't work out what I'm doing wrong. Also is there a simpler way to do this?
As discussed below i've managed to fix the issue by adding SET NOCOUNT ON to the original stored procedure. My issue now is I want to do a second stored procedure in the same code but it only seems to work for one. They both work individually however. So either I have to reopen the connection or use 2 on the defined variables? Here is the code:
Dim rs As ADODB.Recordset
Dim cnSQL As ADODB.Connection
Dim sqlcommand As ADODB.Command, prm As Object, prm2 As Object
Set cnSQL = New ADODB.Connection
cnSQL.Open "Provider=SQLOLEDB; Data Source=bddc1didw1;Initial Catalog=Actuarial; Trusted_connection=Yes; Integrated Security='SSPI'"
Set sqlcommand = New ADODB.Command
sqlcommand.ActiveConnection = cnSQL
'groupdates
sqlcommand.CommandType = adCmdStoredProc
sqlcommand.CommandText = "GroupDate"
Set prm = sqlcommand.CreateParameter("GroupNumberEntry", adVarChar, adParamInput, 5)
Set prm2 = sqlcommand.CreateParameter("ValuationDateEntry", adDate, adParamInput)
sqlcommand.Parameters.Append prm
sqlcommand.Parameters.Append prm2
sqlcommand.Parameters("GroupNumberEntry").Value = "01132"
sqlcommand.Parameters("ValuationDateEntry").Value = "08-31-2019"
Set rs = New ADODB.Recordset
rs.CursorType = adOpenStatic
rs.LockType = adLockOptimistic
rs.Open sqlcommand
ActiveSheet.Range("a2").CopyFromRecordset rs
'GroupCommissions
sqlcommand.CommandType = adCmdStoredProc
sqlcommand.CommandText = "GroupCommissions"
Set prm = sqlcommand.CreateParameter("GroupNumberEntry", adVarChar, adParamInput, 5)
sqlcommand.Parameters.Append prm
sqlcommand.Parameters("GroupNumberEntry").Value = "01132"
Set rs = New ADODB.Recordset
rs.CursorType = adOpenStatic
rs.LockType = adLockOptimistic
rs.Open sqlcommand
ActiveSheet.Range("DB2").CopyFromRecordset rs
Try replacing that line with something like this:
Set prm = sqlcommand.CreateParameter("GroupNumberEntry", adVarChar, GroupNumberEntry, 255)
Set the field type and length according to how your proc is defined.
Your code looked OK to me so I copied it into Excel (2016...) and tried it. It gave me an error on that line but adding the additional parameter values to CreateParameter fixed the issue. shrug It shouldn't matter since those are optional parameters, unless there is something maybe at the provider level.
you can try just sending the SQL PROCEDURE straight through as a CALL function.
Take a look at this:
Public connDB As New ADODB.Connection
Public rs As New ADODB.Recordset
Public strSQL As String
Public strConnectionstring As String
Public strServer As String
Public strDBase As String
Public strUser As String
Public strPwd As String
Public PayrollDate As String
Sub WriteStoredProcedure()
PayrollDate = "2017/05/25"
Call ConnectDatabase
On Error GoTo errSP
strSQL = "EXEC spAgeRange '" & PayrollDate & "'"
connDB.Execute (strSQL)
Exit Sub
errSP:
MsgBox Err.Description
End Sub
Sub ConnectDatabase()
If connDB.State = 1 Then connDB.Close
On Error GoTo ErrConnect
strServer = "SERVERNAME" ‘The name or IP Address of the SQL Server
strDBase = "TestDB"
strUser = "" 'leave this blank for Windows authentication
strPwd = ""
If strPwd > "" Then
strConnectionstring = "DRIVER={SQL Server};Server=" & strServer & ";Database=" & strDBase & ";Uid=" & strUser & ";Pwd=" & strPwd & ";Connection Timeout=30;"
Else
strConnectionstring = "DRIVER={SQL Server};SERVER=" & strServer & ";Trusted_Connection=yes;DATABASE=" & strDBase 'Windows authentication
End If
connDB.ConnectionTimeout = 30
connDB.Open strConnectionstring
Exit Sub
ErrConnect:
MsgBox Err.Description
End Sub

Call a stored procedure from VBA

I'm pretty new to SQL and VBA and I've written the following query in SQL Server:
ALTER PROCEDURE SP_insert_search_archive
#IP_Address VARCHAR(20),
#DT VARCHAR(30),
#search_word VARCHAR(50),
#search_time TIME
AS
INSERT INTO Search_Archive
values (#IP_Address, #DT, #search_word, #search_time);
Now I would like to execute this stored procedure in VBA (Excel):
Dim StartTime As Double
Dim SecondsElapsed As Double
Dim con As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim par As String
Dim WSP1 As Worksheet
Set con = New ADODB.Connection
Set cmd = New ADODB.Command
Set rs = New ADODB.Recordset
StartTime = Timer
Application.DisplayStatusBar = True
Application.StatusBar = "Contacting SQL Server..."
con.Open "Provider=SQLOLEDB;Data Source=localhost;Initial Catalog=master;Integrated Security=SSPI;Trusted_Connection=Yes;"
cmd.ActiveConnection = con
SecondsElapsed = Round(Timer - StartTime, 4)
Dim search_word As String
search_word = Range("D2").Text
Dim IP As String
IP = GetMyPublicIP
cmd.Parameters.Append cmd.CreateParameter("IP", adVarChar, adParamInput, 20, IP)
cmd.Parameters.Append cmd.CreateParameter("DT", adVarChar, adParamInput, 30, Now)
cmd.Parameters.Append cmd.CreateParameter("Search Word", adVarChar, adParamInput, 50, search_word)
cmd.Parameters.Append cmd.CreateParameter("Search Time", adVarChar, adParamInput, 20, SecondsElapsed)
cmd.CommandText = "SP_insert_search_archive"
Set rs = cmd.Execute(, , adCmdStoredProc)
rs.Close
Set rs = Nothing
Set cmd = Nothing
MsgBox (DT)
con.Close
Set con = Nothing
When I'm activating the macro, I get this error:
Runtime error '-2147217900 (80040e14)':
Procedure or function SP_insert_search_archive has too many arguments specified
possible that the issue is with the name of the parameters, you left spaces in them instead of separating with "_" ("Search Word" instead of "search_word")

SQL Stored Procedure times out in Access

The following SP times out when executed from Access VBA. It works fine when executed from the management console. If relevant, the server does has a high ping time:
Dim cnn As ADODB.Connection
Dim cmd As New ADODB.Command, rs As New ADODB.Recordset, param As New ADODB.Parameter
Dim fld As ADODB.Field
Dim stMessage As String
Set cnn = New ADODB.Connection
cnn.ConnectionString = "DRIVER=SQL Server;SERVER=server01;DATABASE=db_a;Trusted_Connection=Yes"
cnn.Open cnn.ConnectionString
Set cmd = New ADODB.Command
cmd.ActiveConnection = cnn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "we_ci_db.stprUpdateValuesInitial_A"
Set param = cmd.CreateParameter("#DataSet", adInteger, adParamInput, , stDataSet)
cmd.Parameters.Append param
rs.CursorType = adOpenStatic
rs.CursorLocation = adUseClient
rs.LockType = adLockOptimistic
Set rs = cmd.Execute
exit1:
Set cmd = Nothing
Set rs = Nothing
Exit Function
You can set the timeout using CommandTimeout property of ADODB.Command objects:
// set a very high number of seconds before timeout
cmd.CommandTimeout = 9999999

Bind Access form to the results from a Stored Procedure

I am trying to return the results of a stored procedure to a form. I have managed to iterate thru the results using an ADO recordset, but cannot bind the results to the form..
Here is the VBA code:
Private Sub RetrieveSiteInformation()
Dim cmd As New ADODB.Command
Dim cnn As New ADODB.Connection
Dim rs As ADODB.Recordset, f As ADODB.Field
With cnn
.Provider = "SQLOLEDB"
.ConnectionString =
"data source=UKFCSVR;initial catalog=ACACB;Trusted_Connection=Yes"
.Open
End With
Dim param1 As ADODB.Parameter
If Nz(txtSiteID_Search.Value, vbNullString) <> vbNullString Then
Set param1 = cmd.CreateParameter("#SiteID", adBigInt, adParamInput)
param1.Value = txtSiteID_Search.Value
cmd.Parameters.Append param1
End If
With cmd
.ActiveConnection = cnn
.CommandText = "spSiteInformation_Retrieve"
.CommandType = adCmdStoredProc
**' THIS FAILS**
Me.Recordset = .Execute
**' THIS LOOP WORKS FINE**
' Set rs = .Execute
' rs.MoveFirst
' For Each f In rs.Fields
' Debug.Print f.Name
' Next
' With rs
' Do While Not .EOF
' Debug.Print ![CompanyName] & " " & ![Postcode]
' .MoveNext
' Loop
' End With
End With
cnn.Close
End Sub
Okay, I have tested this example. It includes changes to suit my set-up which I have left in, rather than guessing at your set-up. Most of this is taken from http://support.microsoft.com/kb/281998/EN-US/
Dim cn As New ADODB.Connection
Dim cmd As New ADODB.Command
Dim param1 As New ADODB.Parameter
With cn
.Provider = "Microsoft.Access.OLEDB.10.0"
.Properties("Data Provider").Value = "SQLOLEDB"
.Properties("Data Source").Value = "Server"
.Properties("Integrated Security").Value = "SSPI"
.Properties("Initial Catalog").Value = "Test"
.Open
End With
txtSiteID_Search = 1
If Nz(txtSiteID_Search, vbNullString) <> vbNullString Then
Set param1 = cmd.CreateParameter("#SiteID", adBigInt, adParamInput)
param1.Value = txtSiteID_Search
cmd.Parameters.Append param1
End If
With cmd
.ActiveConnection = cn
.CommandText = "spSiteInformation_Retrieve"
.CommandType = adCmdStoredProc
Set Me.Recordset = .Execute
End With
Forget ADO. Create a passthru query in Access, with property ReturnsRecords = True.
Bind your form to that passthru query.
Using VBA, change the .SQL property of that QueryDef object, then open the form. You're done.
Set qry = CurrentDb.QueryDefs("myQryDef")
qry.SQL = "exec spMyStoredProc " & "'argument1'"
You need to use Set whenever you assign an object reference in VBA.
Change Me.Recordset = .Execute to Set Me.Recordset = .Execute.
Also, you probably need to open it with a supported cursor type. I don't think there's a way to change the cursor type if you use the Execute method on the Command object. You'll have to create the Recordset separately.
Set rs = New ADODB.Recordset
rs.Open cmd, , adOpenKeyset
Set Me.Recordset = rs

How to create an ADODB Recordset From a Table Valued Function with Named Parameters

This works:
Dim rst As New ADODB.Recordset
rst.Open "SELECT * FROM dbo.ftblTest(1,2,3)", CP.Connection, adOpenKeyset, adLockReadOnly
But it would be nicer to do this:
rst.Open "SELECT * FROM dbo.ftblTest(#Param1=1,#Param2=2,#Param3=3)", CP.Connection, adOpenKeyset, adLockReadOnly
If I try the second method I get the error: "parameters were not supplied for the function ftblTest"
Is it possible to use named parameters with multi-statement table-valued functions?
Edit 1: Examples Added Using Command Object
First the SQL
create function ftblTest (#Input int)
RETURNS #Results TABLE (
OutputField int
)
AS
BEGIN
INSERT INTO #Results SELECT #Input
Return
End
Some Code (run from inside an Access 2003 ADP, with a connection to the correct SQL DB)
Public Sub test()
Dim rst As New ADODB.Recordset
Dim cmd As New ADODB.Command
'method 1 works
rst.Open "SELECT * FROM dbo.ftblTest(2)", CurrentProject.Connection, adOpenKeyset, adLockReadOnly
Debug.Print rst.Fields(0)
rst.Close
With cmd
.ActiveConnection = CurrentProject.Connection
.CommandType = adCmdTable
'method 2 works
.CommandText = "dbo.ftblTest(3)"
Set rst = cmd.Execute
Debug.Print rst.Fields(0)
'method 3 fails
.CreateParameter "#Input", adInteger, adParamInput, , 4
.CommandText = "dbo.ftblTest(#Input)"
Set rst = cmd.Execute 'error here:-2147217900 Must declare the scalar variable "#Input".
Debug.Print rst.Fields(0)
End With
End Sub
How can I get the named parameters to work in method 3?
Edit 2: test code modified to use Parameters.Append
Public Sub test()
Dim rst As New ADODB.Recordset
Dim cmd As New ADODB.Command
Dim p As New ADODB.Parameter
With cmd
.ActiveConnection = CurrentProject.Connection
.CommandType = adCmdTable
'Parameter Append method fails
p = .CreateParameter("#Input", adInteger, adParamInput, , 4)
Debug.Print p.Name, p.Type = adInteger, p.Direction = adParamInput, p.SIZE, p.Value 'note that name not set!
With p
.Name = "#Input"
.Type = adInteger
.Direction = adParamInput
.SIZE = 4 'this shouldn't be needed
.Value = 4
End With
Debug.Print p.Name, p.Type = adInteger, p.Direction = adParamInput, p.SIZE, p.Value 'properties now set
.Parameters.Append p
.CommandText = "dbo.ftblTest(#Input)"
Set rst = cmd.Execute 'error here:-2147217900 Must declare the scalar variable "#Input".
Debug.Print rst.Fields(0)
End With
End Sub
this still doesn't work.
Edit 3: I removed the # from create parameter
as suggested and tried the CommandText 3 ways and got 3 different errors:
.CommandText = "dbo.ftblTest"
error: Parameters were not supplied for the function 'dbo.ftblTest'.
.CommandText = "dbo.ftblTest()"
error: An insufficient number of arguments were supplied for the procedure or function dbo.ftblTest.
.CommandText = "dbo.ftblTest(Input)"
error: "Input" is not a recognized table hints option. If it is intended as a parameter to a table-valued function or to the CHANGETABLE function, ensure that your database compatibility mode is set to 90.
This should work:
Dim cmd As New ADODB.Command
With cmd
.ActiveConnection = CurrentProject.Connection
.CommandType = adCmdTable
'you need to add question a mark for each parameter
.CommandText = "dbo.ftblTest(?)"
'you can even add a order by expression like:
.CommandText = "dbo.ftblTest(?) ORDER BY ..."
.Parameters.Append .CreateParameter("#Input", adInteger, adParamInput, , 4)
Set rst = cmd.Execute
Debug.Print rst.Fields(0)
End With
Yes, you can use parameters with a table function.
rst.Open "SELECT * FROM dbo.ftblTest(#Param1,#Param2,#Param3)", CP.Connection, adOpenKeyset, adLockReadOnly
Before you open the database connection add parameters and set their values.
Don't use the # in the name of your parameter and don't list the parameter by name in the command text. I've always done this with a stored procedure, so I'm not sure exactly how the paranethesis are handle for the command text.
try:
.CreateParameter "Input", adInteger, adParamInput, , 4
And:
.CommandText = "dbo.ftblTest()"
Or:
.CommandText = "dbo.ftblTest"

Resources