Call Oracle stored procedure with VBA using a refcursor - sql

I have stored procedure in Oracle:
create or replace procedure testproc (articlenr in number, storenr in number, cweek in varchar, prc out sys_refcursor)
is begin
open prc for
select * from weekly_revenues
where
article = articlenr
and period = cweek
and store = storenr
;
end;
I can call that function perfectly with the following SQL code:
variable rc refcursor;
exec testproc(123,345,'201705',:rc);
print rc;
That code gives me all the sales data for article 123, store 345 in week 5 of 2017.
Now, I want to call that stored procedure from VBA and I've tried the following code:
Sub ConnectToOracle()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim cmd As New ADODB.Command
Dim param1 As New ADODB.Parameter
Dim param2 As New ADODB.Parameter
Dim arr As Variant
connstr = "Provider=msdaora;Data Source=###;User Id=###;Password=###;"
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
cn.Open connstr
cmd.CommandText = "testproc"
cmd.ActiveConnection = cn
cmd.CommandType = adCmdStoredProc
Set param1 = cmd.CreateParameter("articlenr", adInteger, adParamInput, , 47)
Set param2 = cmd.CreateParameter("storenr", adInteger, adParamInput, , 281)
Set param3 = cmd.CreateParameter("cweek", adVarChar, adParamInput, 10, "201705")
Set param4 = cmd.CreateParameter("prc", adVariant, adParamOutput, , Null)
cmd.Parameters.Append param1
cmd.Parameters.Append param2
cmd.Parameters.Append param3
cmd.Parameters.Append param4
Set rs = cmd.Execute
arr = rs.GetRows
'Work with array...
End Sub
However, I get an arrow for the
Set rs = cmd.Execute
line ("ORA-0136: illegal variable name/number"). Does anyone know how I can get my code to run? I'm not sure whether the variable for the refcursor needs to be declared in a different way (as in the second code snippet), but I'm not sure whether that is the mistake or not.
Thanks!

I found a solution by accident.
If I don't define the ref_cursor parameter, it works.
cmd.CommandText = "testproc"
cmd.ActiveConnection = cn
cmd.CommandType = adCmdStoredProc
Set param1 = cmd.CreateParameter("articlenr", adInteger, adParamInput, , 47)
Set param2 = cmd.CreateParameter("storenr", adInteger, adParamInput, , 281)
Set param3 = cmd.CreateParameter("cweek", adVarChar, adParamInput, 10, "201705")
'Next line not needed
'Set param4 = cmd.CreateParameter("prc", adVariant, adParamOutput, , Null)
cmd.Parameters.Append param1
cmd.Parameters.Append param2
cmd.Parameters.Append param3
'Next line not needed
'cmd.Parameters.Append param4
Set rs = cmd.Execute
This works, apparently the ref_cursor specification is not needed and happens by default :)

Try this one:
Cmd.Properties ("PLSQLRSet") = TRUE
Set rs = cmd.Execute
arr = rs.GetRows
'Work with array...

Related

When executing the stored procedure from VBA getting error "Procedure or function expects parameter #empid which is not passed"

I have written a stored procedure to insert the data into a table. When I execute that into SQL Server 2012 it works fine while in VBA throws error
procedure or function expects parameter #empid which was not provided
I tried to resolve with different combinations of connection strings, CommandType etc but it does not resolve. While code seems perfectly fine, please assist me to resolve it.
Stored procedure:
CREATE PROCEDURE [dbo].[spInsertDataIntoEmployee]
#empid INT,
#empname VARCHAR(20),
#empage INT,
#empsalary DECIMAL(8,2)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO [dbo].[employee] (empid, empname, empage, empsalary)
VALUES (#empid, #empname, #empage, #empsalary)
END
VBA code:
Private Sub Exec_StoredProcFromExcel_Click()
Dim con As ADODB.Connection
Dim res As ADODB.Recordset
Dim mobjCmd As ADODB.Command
Dim strConn As String
Dim par1 As Object
Dim par2 As Object
Dim par3 As Object
Dim par4 As Object
'Dim empname As Varchar
'Dim empage As Integer
'Dim empsalary As Single
Dim indRecordSetFields As Integer
'Dim strQuery As String
'con.Close
Set con = New ADODB.Connection
Set res = New ADODB.Recordset
Set mobjCmd = New ADODB.Command
strConn = "Driver={SQL Server Native Client 11.0};Server=localhost;Database=test;Trusted_Connection=yes;"
'strConn = "Provider=SQLOLEDB; Data Source=localhost; Initial Catalog=test; Integrated Security=SSPI;"
con.Open strConn, adOpenStatic, adLockOptimistic
Set par1 = mobjCmd.CreateParameter("#empid", adInteger, adParamInput)
Set par2 = mobjCmd.CreateParameter("#empname", adVarChar, adParamInput, 30)
Set par3 = mobjCmd.CreateParameter("#empage", adInteger, adParamInput)
Set par4 = mobjCmd.CreateParameter("#empsalary", adDouble, adParamInput)
With mobjCmd
.ActiveConnection = con
.CommandText = "Exec [dbo].[spInsertDataIntoEmployee]"
.CommandType = 1 'adCmdStoredProc=4 does not work while adCmdText=1 and adCmdUnknown=8 both work for me
.CommandTimeout = 45
.Parameters.Append par1
.Parameters("#empid").Value = 111
.Parameters.Append par2
.Parameters("#empname").Value = "majid rajih"
.Parameters.Append par3
.Parameters("#empage").Value = 34
.Parameters.Append par4
.Parameters("#empsalary").Value = 200000
'.Parameters.Append .CreateParameter("#empid", adInteger, adParamInput, 111)
'.Parameters.Append .CreateParameter("#empname", adVarChar, adParamInput, 20, "majid khan")
'.Parameters.Append .CreateParameter("#empage", adInteger, adParamInput, 30)
'.Parameters.Append .CreateParameter("#empsalary", adSingle, adParamInput, 250000)
'.Parameters.Append .CreateParameter("#empid", adInteger, adParamInput, , ThisWorkbook.Sheets("employee").Range("A2").Value)
'.Parameters.Append .CreateParameter("#empname", adVarChar, adParamInput, 20, ThisWorkbook.Sheets("employee").Range("B2").Value)
'.Parameters.Append .CreateParameter("#empage", adInteger, adParamInput, , ThisWorkbook.Sheets("employee").Range("C2").Value)
'.Parameters.Append .CreateParameter("#empsalary", adSingle, adParamInput, , ThisWorkbook.Sheets("employee").Range("D2").Value)
' repeat as many times as you have parameters
.Execute
End With
'With res
'res.CursorType = adOpenStatic
'res.LockType = adLockOptimistic
'res.Open mobjCmd 'This executed the stored proc
'End With
End Sub
You are running the command in the text mode.
Your full query is Exec [dbo].[spInsertDataIntoEmployee] which does not include any parameters.
CommandType should be adCmdStoredProc, and CommandText should be the procedure name, without exec.
.CommandType = adCmdStoredProc
.CommandText = "[dbo].[spInsertDataIntoEmployee]"
If you want to keep adCmdText, list all parameters in the query:
.CommandType = adCmdText
.CommandText = "exec [dbo].[spInsertDataIntoEmployee] #empid, #empname, #empage, #empsalary"
.CommandText = "spInsertDataIntoEmployee"
And try to send everything as nvarchar.

VBA Access more than 2 CreateParameter

I need to create an Access program but I am having trouble.
Here is the problem.
When I type information as below picture, all of the information should be inserted to the Listbox. 'BlendID' and 'Blend Method' are same for all element and only 'Precursor's' information change. So when I typed two item of precursor, there need to be two rows but I only get 1 data in the list box.
(Precursor2's information should be inserted in listbox but it is not working now)
Here is my code
Private Sub AddToListBlend_Click()
Dim cmd As ADODB.Command
Dim conn As ADODB.Connection
Dim strConn As String
Dim par As ADODB.Parameter 'input
'Dim introw As Integer
'On Error GoTo errorhandle
'introw = ListBlend.ListIndex + 1
strConn = "DRIVER=SQL Server;SERVER=CHU-AS-0004;DATABASE=RTC_LaplaceD_DEV;Trusted_Connection=Yes;"
Set conn = New ADODB.Connection
conn.Open strConn 'open connection
If IsNull(TextRequestNo.value) Or TextRequestNo.value = "" Then
MsgBox ("Please select Request No first")
Else
Set cmd = New ADODB.Command
cmd.CommandText = "dbo.AddBlendPrac"
cmd.CommandType = adCmdStoredProc
cmd.ActiveConnection = conn
Set par = cmd.CreateParameter("#BlendID", adVarChar, adParamInput, 50, TextB10.value)
cmd.parameters.Append par
Set par = cmd.CreateParameter("#BlendMethod", adVarChar, adParamInput, 50, TextB11.value)
cmd.parameters.Append par
Set par = cmd.CreateParameter("#RequestID", adVarChar, adParamInput, 50, TextRequestNo.value)
cmd.parameters.Append par
Set par = cmd.CreateParameter("#SampleID", adVarChar, adParamInput, 50, TextB12.value)
cmd.parameters.Append par
Set par = cmd.CreateParameter("#WLocation", adVarChar, adParamInput, 50, WLocation1.value)
cmd.parameters.Append par
cmd.Execute
conn.Close 'close connection
Set conn = Nothing
Set cmd = Nothing
MsgBox "Succeeded"
List731.Requery
End If
End Sub
I am aware that I need to add Precursor2's information but I do not know how to do it. As you can see first information is inserted to the ListBox, but second one is not.
Would you please share your idea about this?

Executing parameterised T-SQL stored procedure in Access vba

I'm getting a "Run time error (13): type mismatch" error when I attempt to execute the below sproc from an after update event in Access. My sproc has the #Season as nvarchar(max) and #Year as int in the SQL (MSSQL2014). Any ideas as to the cause? I've been search all day but no joy as yet. Here is the code:
Private Sub Event_Click()
Dim cnn1 As New ADODB.Connection
Dim cmd As New ADODB.Command
Set cnn1 = New ADODB.Connection
cnn1.ConnectionString = "<connection string snipped but works OK>"
cnn1.ConnectionTimeout = 30
cnn1.Open
vSeason = Me.ComboBox1.Value
vYear = Me.ComboBox2.Value
With cmd
.ActiveConnection = cnn1
.CommandText = "dbo.StoredProcedure"
.CommandType = 4
.CommandTimeout = 0
.Parameters.Append .CreateParameter("#Season", adVarChar, adParamInput, vSeason)
.Parameters.Append .CreateParameter("#Year", adInteger, adParamInput, vYear)
End With
cnn1.Close
Set cnn1 = Nothing
Would be grateful for any pointers here. Any further info needed let me know.
I think the problem is that CreateParameter need size for adVarChar datatype before its value.
try something like:
.Parameters.Append .CreateParameter("#Season", adVarChar, adParamInput, 200, vSeason)
in your code the value vSeason is passed as size parameter,
you are passing a string as integer to CreateParameter, this is the type mismatch error
I hope this helps

Visual Basic 6.0 +Sql Server Stored procedure Timeout issue

Sir,
I am using vb6.0 and sql server 2005. I wrote a small procedure and it return immediate result in sql server but in vb 6.0 it return timeout. Any idea for any body? Please help?
My Procedure:
Alter procedure
[dbo].[SpRptSalesDayBookSummary](#liComid integer,#liPerid integer,#ad_dtfrm DateTime,#ad_dtto DateTime)
AS
begin
SET NOCOUNT ON;
Select SaleDate,Sum(Grand) as tot
from SalesMaster a,SalesDet b
Where a.id=b.RefId
And a.CompanyId= #liComid
And a.PeriodId=#liPerid
And a.SaleDate Between #ad_dtfrm And #ad_dtto
Group By SaleDate Order By SaleDate
End
My vb code:
Dim cmd As New ADODB.Command
Dim rs1 As New ADODB.Recordset
Dim param2 As ADODB.Parameter
Dim param3 As ADODB.Parameter
Dim param4 As ADODB.Parameter
Dim param5 As ADODB.Parameter
g_objData.DBConn.CursorLocation = adUseClient
Set cmd.ActiveConnection = g_objData.DBConn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "SpRptSalesDayBookSummary"
Set param2 = cmd.CreateParameter("Input", adInteger, adParamInput)
cmd.Parameters.Append param2
param2.value = 20
Set param3 = cmd.CreateParameter("Input", adInteger, adParamInput)
cmd.Parameters.Append param3
param3.value = 8
Set param4 = cmd.CreateParameter("Input", adDate, adParamInput)
cmd.Parameters.Append param4
param4.value = Format(PD_DtFrm, "yyyy-mm-dd")
Set param5 = cmd.CreateParameter("Input", adDate, adParamInput)
cmd.Parameters.Append param5
param5.value = Format(PD_DtTo, "yyyy-mm-dd")
Set rs1 = cmd.Execute
Please help.
You don't say what the .CommandTimeout property is against the Connection object but you may need to up it. I'm sure you can also specify the .CommandTimeout property against the command object too - try setting it to 600 (10 minutes).
I've seen code before that sets the CommandTimeout property against a connection in seconds, thinking it's minutes!

Pass an array of ADODB parameters to function?

I am attempting to create my ADODBcommand and parameters in the calligng code, so that I can pass them into a generic SQL function, but I get an error when retrieving the parameter from the list:
Dim prm As ADODB.Parameter
Dim cmd As ADODB.Command
Dim ParameterList(0) As Variant
Value = Cells(3,3).Value
Set cmd = New ADODB.Command
Set prm = cmd.CreateParameter("#Field", adVarChar, adParamInput, 50)
cmd.Parameters.Append prm
cmd.Parameters("#Field").Value = Value
ParameterList(0) = prm
Call SQLFunc(Data, SQLStr, adCmdStoredProc, cmd, ParameterList)
.
.
sub SQLFunc(ByRef Data as Variant, SQLStr as String, CommandType As ADODB.CommandTypeEnum, ByRef cmd As ADODB.Command, ParamList As Variant)
.
.
.
If cmd.CommandType <> adCmdStoredProc Then
cmd.Execute
Else
'Append the parameters
For i = LBound(ParamList, 1) To UBound(ParamList, 1)
Dim TempParam As ADODB.Parameter
Set TempParam = ParamList(i)
cmd.Parameters.Append TempParam 'Error here
Next
Set Rst = cmd.Execute
Could anyone please advise how I can achieve this?
After
ParameterList(0) = prm
ParameterList(0) is Empty, to resolve this;
set ParameterList(0) = prm
I would also strongly type this so instead of variant use Dim ParameterList(0) As ADODB.Parameter
The error you see occurs because you already append the parameter to the command before calling SQLFunc, in which you illegaly attempt to do so again. Parameter names must be unique when bound to a command.
You could remove the binding and use;
Set prm = cmd.CreateParameter("#Field", adVarChar, adParamInput, 50)
prm.Value = Value
Then prm remains independent of cmd.