Calling SQL Server stored procedure from vb.net 2008 error - sql-server

I am trying to execute a SQL Server stored procedure from vb.net 2008. But I get the error
Procedure or function 'Sp_Messages_Display' expects parameter '#MsgSno', which was not supplied.
Here is my code
Public Function Load(ByVal CnnStr As String, ByVal MsgSno As Long, ByVal Msg_Status As eMsgStatus) As ADODB.Recordset
Dim Cnn As ADODB.Connection
Dim Com As ADODB.Command
Cnn = New ADODB.Connection
Cnn.CursorLocation = ADODB.CursorLocationEnum.adUseClient
Cnn.ConnectionString = CnnStr
Cnn.Open()
Com = New ADODB.Command
Com.ActiveConnection = Cnn
With Com
.CommandType = ADODB.CommandTypeEnum.adCmdStoredProc
.CommandText = "Sp_Messages_Display"
.CreateParameter("#MsgSno", ADODB.DataTypeEnum.adBigInt, ADODB.ParameterDirectionEnum.adParamInput, 4, MsgSno)
.CreateParameter("#Msg_Status", ADODB.DataTypeEnum.adSmallInt, ADODB.ParameterDirectionEnum.adParamInput, 4, Msg_Status)
Load = .Execute(RecordsAffected)
SqlError = Err.Description
End With
If Not Load.EOF Then
With Me
.MsgSno = Load.Fields("MsgSno").Value
End With
End If
Com.ActiveConnection = Nothing
Cnn = Nothing
End Function
Please help me where I am wrong. Thanks in advance

You need to add parameters to the Command, the CreateParameter only creates a new instance without adding it to the collection of the Command:
With Com
CommandType = ADODB.CommandTypeEnum.adCmdStoredProc
.CommandText = "Sp_Messages_Display"
.Parameters.Add("#MsgSno", ADODB.DataTypeEnum.adBigInt, ADODB.ParameterDirectionEnum.adParamInput, 4, MsgSno)
.Parameters.Add("#Msg_Status", ADODB.DataTypeEnum.adSmallInt, ADODB.ParameterDirectionEnum.adParamInput, 4, Msg_Status)
Load = .Execute(RecordsAffected)
SqlError = Err.Description
End With
I now believe you are not using VB.NET, but VB, in that case this is the way to go from MSDN:
ccmd.parameters.Append ccmd.CreateParameter(, adInteger, adParamReturnValue, , NULL) ' return value
ccmd.parameters.Append ccmd.CreateParameter("InParam", adVarChar, adParamInput, 20, "hello world") ' input parameter
ccmd.parameters.Append ccmd.CreateParameter("OutParam", adVarChar, adParamOuput, 20, NULL) ' output parameter

From the documentation to CreateParameter:
This method does not automatically append the Parameter object to the Parameters collection of a Command object.
You need to add the parameter you have created to the collection.

Related

VBA Execution of SQL Stored Procedure Fails with adDecimal Datatype

I would appreciate any help on this problem that has me stumped:
I am attempting to execute a SQL Server 2008 stored procedure from Access 365 VBA and keep faulting out with "Multiple-step OLE DB operation generated errors".
This fault began when I changed a column in the target table from int datatype to decimal(3,1). (I now need to be able to store a single digit to the right of the decimal).
For troubleshooting/ testing, I stripped the stored procedure down to update this column only. (OCR_Freq is the update column, OcrxId is the record id).
I have verified/tried:
1) The table column is set to decimal(3,1).
2) The data type in the stored procedure variable is decimal(3,1).
3) The stored procedure executes without issue from SQL Server
Management Studio.
4) Changing the column datatype to decimal(18,4) had no effect.
4) The vba code below executes without issue if the DataType is
adInteger.
5) I use this code to execute a number of other stored procedures
without issue.
'VBA CODE:
Dim Comm As ADODB.Command
Dim lngRecordsAffected As Long
Dim param1 As New ADODB.Parameter
Dim param2 As New ADODB.Parameter
'************************************************
Dim ocrxid As Long
Dim OCR_Freq As Variant
Dim x As Single
'testing the formatting
x = 7.2 'doesn't work
'OCR_Freq = Round(x, 1) 'doesn't work
'OCR_Freq = CDec(x) 'doesn't work
'OCR_Freq = Round(OCR_Freq, 1) 'doesn't work
OCR_Freq = CDec(Format(x, "00.0")) 'doesn't work
'connection stuff
If con.State = adStateClosed Then
con.ConnectionString = conConnection
con.Open
End If
Set Comm = New ADODB.Command
With Comm
.ActiveConnection = con
.CommandType = adCmdStoredProc
.CommandText = "up_EOCR_TEST"
'--- ADD PARAMETERS --------------------------------
'OCR_Freq decimal(3,1)
Set param1 = Comm.CreateParameter("#OCR_Freq", adDecimal,
adParamInput, , OCR_Freq)
Comm.Parameters.Append param1
'test record id
Set param2 = Comm.CreateParameter("#OcrxId", adInteger,
adParamInput, , 8053)
Comm.Parameters.Append param2
.Execute lngRecordsAffected
End With
'END VBA CODE
//SQL Stored Procedure:
#OCR_Freq decimal(3,1) = null,
#OcrxId int = null
as
begin
UPDATE dbo.OCRX SET OCR_Freq=#OCR_Freq WHERE OCR_ID=#OcrxId;
END
The error I am getting is "Multiple-step OLE DB operation generated errors"
The above leads me to conclude that I am not properly "preparing" the value in vba for the stored procedure execution- adDecimal is not happy with my variable...
but I am at loss as how to move forward. Any help would be appreciated.
Well, the solution was staring me in the face- I forgot to set the NumericScale and precision on param1 before appending it:
'VBA CODE CORRECTED:
Dim Comm As ADODB.Command
Dim lngRecordsAffected As Long
Dim param1 As New ADODB.Parameter
Dim param2 As New ADODB.Parameter
'************************************************
Dim ocrxid As Long
Dim OCR_Freq As Variant
Dim x As Single
'testing the formatting
x = 7.5
OCR_Freq = x
'connection stuff
If con.State = adStateClosed Then
con.ConnectionString = conConnection
con.Open
End If
Set Comm = New ADODB.Command
With Comm
.ActiveConnection = con
.CommandType = adCmdStoredProc
.CommandText = "up_EOCR_TEST"
'--- ADD PARAMETERS ---------------------------------------------------
'OCR_Freq decimal(3,1)
Set param1 = Comm.CreateParameter("#OCR_Freq", adDecimal, adParamInput, ,
OCR_Freq)
param1.NumericScale = 1
param1.Precision = 3
Comm.Parameters.Append param1
Set param2 = Comm.CreateParameter("#OcrxId", adInteger, adParamInput, ,
8053)
Comm.Parameters.Append param2
.Execute lngRecordsAffected
End With

Object variable or With block variable not set.

I'm trying to connect SQL Server to Access. I have the connection function in a module. I call this function in another module.
Here is the code in my module:
'Variabel voor SQL Server Connectie
Public SQLConnectie As ADODB.Connection
'Connecten met SQL Server
Public Function DBConn() As ADODB.Connection
If Not (SQLConnectie Is Nothing) Then
Set SQLConnectie = New ADODB.Connection
With SQLConnectie
.CommandTimeout = 15
.Mode = adModeReadWrite
.ConnectionString = "Provider=SQLNCLI11;Server=dafehvmvdsql3;Database=PROVOMotorenfabriek;Integrated Security=SSPI; Persist Security Info=False"
.Open
End With
End If
Set DBConn = SQLConnectie
Set SQLConnectie = Nothing
End Function
And below the code in the module which executes the stored procedure in SQL Server:
Call DBConn.Execute("EXEC spStoringToevoegen " & productielijnMW & ", " & Forms(Formnaam)!cbLijngedeelte & ".............etc
I get the error: Object variable or With block variable not set. Every answer I find says I need to put set in front of some variables but I can't find which one this should be.
Thanks in advance,
Adding this to sample parameters.
As I said my VBA is very rusty (and I find VBA particularly weird language to work with, add Access to that it sounds like a misery to me). It would be much easier if you used some other backend (and language as well). Anyway, here is a sample with parameters in VBA (Excel):
Sub Macro1()
Dim oRecordset1 As ADODB.Recordset
Dim oConnection As ADODB.Connection
Dim oCommand As ADODB.Command
Dim oParameter1 As ADODB.Parameter
Dim oParameter2 As ADODB.Parameter
Set oConnection = New ADODB.Connection
Set oCommand = New ADODB.Command
oConnection.ConnectionString = "Provider=SQLNCLI11.0;Data Source=.\SQLExpress;Trusted_connection=Yes"
oConnection.Open
oCommand.ActiveConnection = oConnection
oCommand.CommandType = 4
oCommand.CommandText = "Northwind.dbo.[CustomersSelectLike]"
Set oParameter1 = oCommand.CreateParameter("#country", 130, 1, -1) ' adWChar
oCommand.Parameters.Append oParameter1
oCommand.Parameters("#country").Value = "USA"
Set oParameter2 = oCommand.CreateParameter("#customer", 130, 1, -1)
oCommand.Parameters.Append oParameter2
oCommand.Parameters("#customer").Value = "%"
Set oRecordset = oCommand.Execute()
Sheet1.Range("A1").CopyFromRecordset (oRecordset)
End Sub

Call SQL stored procedure from VBA - ADO - Named Parameters

Experimenting with VBA ADO with below code to call a stored procedure (with three parameters #p1, #p2, #p3) that writes data to an SQL table (with three columns p1,p2,p3).
Despite having NamedParameters set to true, the parameter names, though populated in the Parameter object, seemingly do not feed through to SQL, i.e. in the SQL table I get < p1,p2,p3> = <7,8,9> instead of <7,9,8>.
Sub UploadShareclassDatatoDB()
Dim Conn As ADODB.Connection
Dim ADODBCmd As ADODB.Command
Dim rs As ADODB.Recordset
NamedParameters = True
Dim i As Integer
Dim sConnect As String
sConnect = "Provider=SQLOLEDB.1;User ID=**;Password=**;Initial Catalog=**;Data Source=**;"
Set Conn = New ADODB.Connection
Conn.ConnectionString = sConnect
Conn.Open
Set ADODBCmd = New ADODB.Command
ADODBCmd.ActiveConnection = Conn
ADODBCmd.CommandText = "test"
ADODBCmd.CommandType = adCmdStoredProc
ADODBCmd.Parameters.Append ADODBCmd.CreateParameter("#p1", adInteger, adParamInput, , 7)
ADODBCmd.Parameters.Append ADODBCmd.CreateParameter("#p3", adInteger, adParamInput, , 8)
ADODBCmd.Parameters.Append ADODBCmd.CreateParameter("#p2", adInteger, adParamInput, , 9)
Set rs = ADODBCmd.Execute()
End Sub
What do I need to do so the procedure is invoked with parameters depending on parameter name rather than the order in which the parameters are constructed by the code?

Receiving an Error " The object you entered is not a valid record set property" access 2013 assigning record set to a form

I am using Access 2013 to upgrade an old application with sql 2012 back end. I have several Stored Procedures with parameters which i need to call and assigned to forms and reports.
The issue i am having is that i get the error "7965" every time i try to assigned the returned record set to the form
i am using the open event of the form and the following code
Private Sub Form_Open(Cancel As Integer)
Dim cmd1 As ADODB.Command
Dim recs1 As New ADODB.Recordset
Dim prm1 As ADODB.Parameter
Dim prm2 As ADODB.Parameter
Dim prm3 As ADODB.Parameter
Set cnn = CreateObject("ADODB.Connection")
cnn.ConnectionString = "DRIVER={SQL Server Native Client 11.0};SERVER=192.168.0.12;DATABASE=SavingsPlusCorp;Trusted_Connection=yes;"
cnn.Open cnn.ConnectionString
Set cmd1 = New ADODB.Command
Set cmd1.ActiveConnection = cnn
cmd1.CommandText = "dbo.iNVENSOLDSp"
cmd1.CommandType = adCmdStoredProc
Set prm1 = cmd1.CreateParameter("#branchid", adInteger, adParamInput, 2)
cmd1.Parameters.Append prm1
Set prm2 = cmd1.CreateParameter(" #Beginning_Date", adDate, adParamInput)
cmd1.Parameters.Append prm2
Set prm3 = cmd1.CreateParameter(" #Ending_Date", adDate, adParamInput)
cmd1.Parameters.Append prm3
Set prm4 = cmd1.CreateParameter("#vENDORID", adInteger, adParamInput, 2)
cmd1.Parameters.Append prm4
Set prm5 = cmd1.CreateParameter("#catID", adInteger, adParamInput, 2)
cmd1.Parameters.Append prm5
prm1.Value = Form_ReportGenerator.Branches
prm2.Value = Form_ReportGenerator.Begin_Date
prm3.Value = Form_ReportGenerator.Ending_Date
prm4.Value = Form_ReportGenerator.Vendors
prm5.Value = Form_ReportGenerator.Category
Set recs1 = CreateObject("ADOdB.recordset")
recs1.CursorType = adOpenKeyset
recs1.CursorLocation = adUseClient
'Set recs1 = cmd1.Execute
'recs1.Open
Set Me.Recordset = cmd1.Execute
I have also tried
set me.Recordset= recs1
with the same results
please help
The solution in the the thread identified as a possible is almost identical to my attempt
In fact I used it to build my attempt
I used the command. Execute and assigned it to my form
Set me.RecordSet = cmd1.execute
It is this line that returns the error
Is their an issue with the provider I am using to connect
I don't understand why it is not working
Please help
I had this problem, spent hours looking for it... turned to be right under my nose:
A function that had work perfectly well, repopulating an Access combo box from Mysql backed, suddenly gave this message after I changed adUseClient to adUseServer for barely relevant reasons. Here's the code (with thanks to Author: Christian Coppes)
Public Function fnADOComboboxSetRS(cmb As String, strSQL As String, strCallingForm As String, Optional StrCnnstring As String)
On Error GoTo fnADOComboboxSetRS_Error
Dim sourceDB As New clsAdoDBHelper
Dim RS1 As New ADODB.Recordset
If Len(StrCnnstring & vbNullString) = 0 Then
sourceDB.Connect CnString
Else
sourceDB.Connect StrCnnstring
End If
Set RS1 = sourceDB.OpenRecordset(strSQL, adUseClient)
Set Application.Forms(strCallingForm).Controls(cmb).Recordset = RS1
fnADOComboboxSetRS_Exit:
If Not RS1 Is Nothing Then
If RS1.State = adStateOpen Then RS1.Close
Set RS1 = Nothing
End If
Exit Function
fnADOComboboxSetRS_Error:
Select Case Err
Case Else
'fnErr "modODBC->fnADOComboboxSetRS", True
Resume fnADOComboboxSetRS_Exit
End Select
End Function
You need to call the Open method of an ADO.Recordset object.
To demonstrate this, first create a simple stored procedure in SQL Server.
USE AdventureWorks2016CTP3;
GO
CREATE PROCEDURE dbo.up_TestPerson
AS
SELECT BusinessEntityID, FirstName, LastName
FROM Person.Person;
Then create a Microsoft Access form with this code behind.
Private Sub Form_Open(Cancel As Integer)
Dim cnn As New ADODB.Connection
cnn.ConnectionString = "DRIVER={SQL Server Native Client 11.0};SERVER=V-SQL16-R;DATABASE=AdventureWorks2016CTP3;Trusted_Connection=yes;"
cnn.Open
Dim cmd1 As New ADODB.Command
Set cmd1.ActiveConnection = cnn
cmd1.CommandText = "dbo.up_TestPerson"
cmd1.CommandType = adCmdStoredProc
Dim rst As New ADODB.Recordset
rst.Open cmd1, , adOpenKeyset, adLockPessimistic
Set Me.Recordset = rst
End Sub
Open the form, and it displays the data.
To demonstrate using a parameter, create a stored procedure like this. (Same as the first stored procedure, except it has a parameter and a WHERE clause.)
CREATE PROCEDURE dbo.up_TestPerson2
(
#PersonType nchar(2)
)
AS
SELECT BusinessEntityID, FirstName, LastName
FROM Person.Person
WHERE PersonType = #PersonType;
Create another Access form with this code behind. (Same as the first form, except for the block where we create and configure the parameter.)
Private Sub Form_Open(Cancel As Integer)
Dim cnn As New ADODB.Connection
cnn.ConnectionString = "DRIVER={SQL Server Native Client 11.0};SERVER=V-SQL16-R;DATABASE=AdventureWorks2016CTP3;Trusted_Connection=yes;"
cnn.Open
Dim cmd1 As New ADODB.Command
Set cmd1.ActiveConnection = cnn
cmd1.CommandText = "dbo.up_TestPerson2"
cmd1.CommandType = adCmdStoredProc
' This is new
Dim prm1 As ADODB.Parameter
Set prm1 = cmd1.CreateParameter("#PersonType", adWChar, adParamInput, 2)
cmd1.Parameters.Append prm1
prm1.Value = "EM"
Dim rst As New ADODB.Recordset
rst.Open cmd1, , adOpenKeyset, adLockPessimistic
Set Me.Recordset = rst
End Sub
Open the form and it displays records matching the parameter.

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