I'm fairly new to VB.NET and Oracle. I'm currently trying to convert functions which call stored procedures using OO4O types to one that uses ODP.NET as part of a maintenance effort to do away with obsolete references.
I think my issue lies with the 3 ".AddTable" commands.
On the Oracle side these parameters are defined as "TABLE OF VARCHAR2(20) INDEX BY BINARY_INTEGER".
I don't have access to the Oracle side or any more information about the stored proc as it is handled by a third party. Both the function snippets are below.
Any advice would be appreciated!
Working Function Using OO4O
Dim oraParams As OracleInProcServer.OraParameters
'Return parameters
oraParams.Add("NUMBER", -1, pmORAPARM_OUTPUT, vbLong)
'Pass parameters to the stored procedure.
oraParams.Add("a_st", strA_st, pmORAPARM_INPUT, vbString)
oraParams.Add("a_st_version", strA_st_version, pmORAPARM_BOTH)
oraParams.Add("a_sc", strA_sc, pmORAPARM_BOTH, vbString)
oraParams.Add("a_ref_date", objA_ref_date, pmORAPARM_INPUT, ORATYPE_DATE)
oraParams.Add("a_create_ic", strA_create_ic, pmORAPARM_INPUT, vbString)
oraParams.Add("a_create_pg", strA_create_pg, pmORAPARM_INPUT, vbString)
oraParams.Add("a_userid", strA_userid, pmORAPARM_INPUT, vbString)
oraParams.AddTable("a_fieldtype_tab", pmORAPARM_INPUT, ORATYPE_VARCHAR2, 1, 20)
oraParams.AddTable("a_fieldnames_tab", pmORAPARM_INPUT, ORATYPE_VARCHAR2, 1, 20)
oraParams.AddTable("a_fieldvalues_tab", pmORAPARM_INPUT, ORATYPE_VARCHAR2, 1, 40)
oraParams.Add("a_nr_of_rows", iA_nr_of_rows, pmORAPARM_INPUT, vbLong)
oraParams.Add("a_modify_reason", strA_modify_reason, pmORAPARM_INPUT, vbString)
g_cOraDatabase.SQL_Execute("Begin :NUMBER:=UNAPISC.CreateSam(:a_st, :a_st_version, :a_sc, :a_ref_date, :a_create_ic, :a_create_pg, :a_userid, :a_fieldtype_tab, :a_fieldnames_tab, :a_fieldvalues_tab, :a_nr_of_rows, :a_modify_reason);commit;end;")
New Function Using ODP.NET
Dim strA_fieldtype_tab As String()
Dim strA_fieldnames_tab As String()
Dim strA_fieldvalues_tab As String()
Dim testOraCMD As New OracleCommand
Dim testCon As New OracleConnection
'DB and Stored Proc Settings
testCon.ConnectionString = "user id=" & g_strDBUser & ";password=" & g_strDBPassword & ";data source=" & g_strDBDatabase & ";"
testCon.Open()
testOraCMD.Connection = testCon
testOraCMD.CommandText = "UNAPISC.CreateSam"
testOraCMD.CommandType = System.Data.CommandType.StoredProcedure
'Return parameters
testOraCMD.Parameters.Add(New OracleParameter("NUMBER", OracleDbType.Long)).Direction = ParameterDirection.ReturnValue
'Pass parameters to the stored procedure.
testOraCMD.Parameters.Add(New OracleParameter("A_ST", OracleDbType.Varchar2, ParameterDirection.Input)).Value = strST
testOraCMD.Parameters.Add(New OracleParameter("A_ST_VERSION", OracleDbType.Varchar2, 2000, ParameterDirection.InputOutput)).Value = strA_st_version
testOraCMD.Parameters.Add(New OracleParameter("A_SC", OracleDbType.Varchar2, 2000, ParameterDirection.InputOutput)).Value = strA_sc
testOraCMD.Parameters.Add(New OracleParameter("A_REF_DATE", OracleDbType.Date, ParameterDirection.Input)).Value = objA_ref_date
testOraCMD.Parameters.Add(New OracleParameter("A_CREATE_IC", OracleDbType.Varchar2, 2000, ParameterDirection.Input)).Value = strA_create_ic
testOraCMD.Parameters.Add(New OracleParameter("A_CREATE_PG", OracleDbType.Varchar2, 2000, ParameterDirection.Input)).Value = strA_create_pg
testOraCMD.Parameters.Add(New OracleParameter("A_USERID", OracleDbType.Varchar2, 2000, ParameterDirection.Input)).Value = strA_userid
Dim f_type As OracleParameter
f_type = testOraCMD.Parameters.Add(New OracleParameter("A_FIELDTYPE_TAB", OracleDbType.Varchar2, ParameterDirection.Input))
f_type.CollectionType = OracleCollectionType.PLSQLAssociativeArray
f_type.Value = strA_fieldtype_tab
f_type.Size = strA_fieldtype_tab.Length
Dim f_name As OracleParameter
f_name = testOraCMD.Parameters.Add(New OracleParameter("A_FIELDNAMES_TAB", OracleDbType.Varchar2, ParameterDirection.Input))
f_name.CollectionType = OracleCollectionType.PLSQLAssociativeArray
f_name.Value = strA_fieldnames_tab
f_name.Size = strA_fieldnames_tab.Length
Dim f_values As OracleParameter
f_values = testOraCMD.Parameters.Add(New OracleParameter("A_FIELDVALUES_TAB", OracleDbType.Varchar2, ParameterDirection.Input))
f_values.CollectionType = OracleCollectionType.PLSQLAssociativeArray
f_values.Value = strA_fieldvalues_tab
f_values.Size = strA_fieldvalues_tab.Length
testOraCMD.Parameters.Add(New OracleParameter("A_NR_OF_ROWS", OracleDbType.Long, ParameterDirection.Input)).Value = iA_nr_of_rows
testOraCMD.Parameters.Add(New OracleParameter("A_MODIFY_REASON", OracleDbType.Varchar2, 2000, ParameterDirection.Input)).Value = strA_modify_reason
'Call Stored Proc
testOraCMD.ExecuteNonQuery()
'Clean up
testCon.Close()
testCon.Dispose()
testOraCMD.Dispose()
If I don't assign a value to the 3 arrays (As no value is assigned in the original working function), I get the message "OracleParameter.Value is invalid". If I assign any single character/ string/ character array/ string array, I receive: "ORA-06502: PL/SQL: numeric or value error: character string buffer too small" & vbLf & "ORA-06512: at line 1"
Instead of
testOraCMD.CommandText = "UNAPISC.CreateSam"
testOraCMD.CommandType = System.Data.CommandType.StoredProcedure
you may try
testOraCMD.CommandText = "Begin :NUMBER := UNAPISC.CreateSam(:a_st, :a_st_version, :a_sc, :a_ref_date, :a_create_ic, :a_create_pg, :a_userid, :a_fieldtype_tab, :a_fieldnames_tab, :a_fieldvalues_tab, :a_nr_of_rows, :a_modify_reason);end;"
testOraCMD.CommandType = System.Data.CommandType.Text
AssociativeArray parameters are added like this:
Dim chngId As Long()
par = testOraCMD.Parameters.Add("chngId", OracleDbType.Int64, ParameterDirection.Input)
par.CollectionType = OracleCollectionType.PLSQLAssociativeArray
par.Value = chngId
par.Size = chngId.Length
Related
I have a problem with calling my functions on Oracle server via VBA.
When I try calling function without parameters. It´s ok.
But, when I Calling functions with parameter. I get error ([Microsoft][ODBC driver for Oracle]Invalid parameter type)
Have any idea?
This is vba code and plsql (I make elementary function for test)
Vba
Private Sub test()
Dim Oracon As ADODB.Connection
Dim cmd As New ADODB.Command
Dim param1 As New ADODB.Parameter
Dim objErr As ADODB.Error
Set Oracon = CreateObject("ADODB.Connection")
mujuser = "xxxx"
mujPWD = "xxxxx"
strConn = "UID=" & mujuser & ";PWD=" & mujPWD & ";driver={Microsoft ODBC for Oracle};" & _
"SERVER=xx.xxx;"
Oracon.ConnectionString = strConn
Oracon.Open
cmd.ActiveConnection = Oracon
cmd.CommandText = "el_test"
cmd.CommandType = adCmdStoredProc
Set param1 = cmd.CreateParameter("P1", adLongVarChar, adParamInput, 256)
cmd.Parameters.Append param1
cmd.Parameters(0).Value = "ahoj1"
cmd.Execute
End Sub
And function
CREATE OR REPLACE FUNCTION EL_TEST
(
P1 IN VARCHAR2
) RETURN VARCHAR2 AS
BEGIN
RETURN 'Ahoj';
END EL_TEST;
Thanky you.
Get function return value with OLEDB
I searched high and low for this but finally solved the problem myself.
My solution is in VBScript but I have represented it in the (untested) code below.
The trick is that the first parameter is the return value.
Private Sub test()
Dim Oracon As ADODB.Connection
Dim cmd As New ADODB.Command
Dim param1 As New ADODB.Parameter
Dim param0 As New ADODB.Parameter
Dim objErr As ADODB.Error
Set Oracon = CreateObject("ADODB.Connection")
mujuser = "xxxx"
mujPWD = "xxxxx"
strConn = "UID=" & mujuser & ";PWD=" & mujPWD & ";driver={Microsoft ODBC for Oracle};" & _
"SERVER=xx.xxx;"
Oracon.ConnectionString = strConn
Oracon.Open
cmd.ActiveConnection = Oracon
cmd.CommandText = "el_test"
cmd.CommandType = adCmdStoredProc
Set param0 = cmd.CreateParameter("P0", adLongVarChar, adParamReturnValue, 256)
Set param1 = cmd.CreateParameter("P1", adLongVarChar, adParamInput, 256)
cmd.Parameters.Append param0
cmd.Parameters.Append param1
cmd.Execute
Dim result As String
result = param0.Value ' Use the variable you set. Same as cmd.Parameters(1).Value '
End Sub
I admit, I've never tried to execute a function like this through code, but I'm surprise this worked without the parameter because the way you have your function set up. I think the way you would want to get the value would be:
select el_test('ahoj1') from dual;
If you made this change from a function to a procedure, I think it will work the way you expect:
CREATE OR REPLACE procedure EL_TEST
( P1 IN VARCHAR2,
p2 out varchar2) is
BEGIN
p2 := 'Ahoj';
END EL_TEST;
And then your VBA would look like this:
Private Sub test()
Dim Oracon As ADODB.Connection
Dim cmd As New ADODB.Command
Dim param1 As New ADODB.Parameter
Dim objErr As ADODB.Error
Set Oracon = CreateObject("ADODB.Connection")
mujuser = "xxxx"
mujPWD = "xxxxxx"
strConn = "UID=" & mujuser & ";PWD=" & mujPWD & _
";driver={Microsoft ODBC for Oracle};SERVER=xxxx-xx"
Oracon.ConnectionString = strConn
Oracon.Open
cmd.ActiveConnection = Oracon
cmd.CommandText = "el_test"
cmd.CommandType = adCmdStoredProc
cmd.NamedParameters = True
cmd.Parameters.Append cmd.CreateParameter("P1", adVarChar, adParamInput, 256, "ahoj1")
cmd.Parameters.Append cmd.CreateParameter("P2", adVarChar, adParamOutput, 256)
cmd.Execute
Dim result As String
result = cmd.Parameters(1).Value
End Sub
I try to get return value of this Oracle stored procedure with VBScript, but everytime returned NULL (nothing), not populate cmd("retVal"). Where is my mistake?
If this stored procedure works fine it must return a integer value like 1 or -2 parameters are passed and change db data, but not return any value in OUT param in stored procedure.
Set connORA = Server.CreateObject("ADODB.Connection")
connORA.ConnectionString = "conninfo"
connORA.Open
Set cmd = Server.CreateObject("ADODB.Command")
Set cmd.ActiveConnection = connORA
cmd.CommandText = "{call procedureName(486954,100002335,'0','0',0,'12-03-2015','X','IPTAL_EDILDI',443,'SAT',?)}"
cmd.Prepared = True
cmd.Parameters.Append cmd.CreateParameter("retVal", 131, 2)
cmd.Execute
Response.Write cmd("retVal")
Set oCmd = Nothing
connORA.Close
Set connORA=nothing
I have an Excel 2013 VBA macro which needs to call an SQL procedure on an Oracle 12c database. The Oracle procedure is executed (it writes the result into a table) but in Excel I receive the error at Set rs = cmd.Execute:
Operation is not allowed when the object is closed
Below the code:
Dim v_userpw As String
Dim cnn As ADODB.Connection
Dim rs As New ADODB.Recordset
Dim cmd As New ADODB.Command
Dim l_userpw, l_reqid, l_pwhash, l_sighash As New ADODB.Parameter
Dim objErr As ADODB.Error
v_userpw = Cells(7, 1).Value
On Error GoTo err_test
'Set cnn = CreateObject("ADODB.Connection")
Set cnn = New ADODB.Connection
cnn.ConnectionString = "Provider=OraOLEDB.Oracle;Data Source=devdb;User ID=db1;Password=db1;"
cnn.Open
Set cmd = New ADODB.Command
Set cmd.ActiveConnection = cnn
Set l_userpw = cmd.CreateParameter("l_userpw", adVarChar, adParamInput, 1024, v_userpw)
cmd.Parameters.Append l_userpw
Set l_reqid = cmd.CreateParameter("l_reqid", adVarChar, adParamOutput, 1024)
cmd.Parameters.Append l_reqid
Set l_pwhash = cmd.CreateParameter("l_pwhash", adVarChar, adParamOutput, 1024)
cmd.Parameters.Append l_pwhash
Set l_sighash = cmd.CreateParameter("l_sighash", adVarChar, adParamOutput, 1024)
cmd.Parameters.Append l_sighash
'cmd.Properties("PLSQLRSet") = True
cmd.CommandText = "{CALL db1.genheader(?, ?, ?, ?)}"
Set rs = cmd.Execute
'cmd.Properties("PLSQLRSet") = False
Cells(8, 1) = rs.Fields("reqid").Value
Cells(9, 1) = rs.Fields("pwhash").Value
Cells(10, 1) = rs.Fields("sighash").Value
cnn.Close
err_test:
MsgBox Error$
For Each objErr In cnn.Errors
MsgBox objErr.Description
Next
cnn.Errors.Clear
Resume Next
The Oracle procedure looks like this:
create or replace procedure genheader (
l_userpw in varchar2,
l_reqid out varchar2,
--l_pwhash out raw,
--l_sighash out raw
l_vpwhash out varchar2,
l_vsighash out varchar2
)
I need to return the values in the predefined cells.
Does the procedure actually return a resultset? It looks like it just returns data using output parameters, so you wouldn't get the results from a recordset, you'd get them from the command parameters after the command executes.
cmd.Execute
Cells(8, 1) = cmd("l_reqid")
Cells(9, 1) = cmd("l_pwhash")
Cells(10, 1) = cmd("l_sighash")
Try testing the connection state to ensure it is open prior to assigning the connection to the ActiveConnection property of the command object. This can cause unstable behavior. If you don't want to do this in code, you can assign a breakpoint prior to the set line of code and check your locals window for the connection state. Also you need to specify the name of the Oracle Stored Procedure
cmd.Name = "genheader"
Cheers,
Boris
To preface this post, I want to say that I am fairly new to Excel 2007 vba macros. I am trying to call an Oracle PL/SQL stored procedure that has a cursor as an output parameter. The procedure spec looks like this:
PROCEDURE get_product
(
out_cur_data OUT SYS_REFCURSOR,
rptid IN NUMBER,
scenario IN VARCHAR2
);
And I have written my macro as:
Sub GetProduct()
Const StartRow As Integer = 4
Dim conn As ADODB.Connection
Set conn = New ADODB.Connection
With conn
.ConnectionString = "<my connection string>"
.Open
End With
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandType = adCmdText
.CommandText = "{call their_package.get_product({out_cur_data 100},?,?)}"
.NamedParameters = True
.Parameters.Append cmd.CreateParameter("rptid", adNumeric, adParamInput, 0, 98)
.Parameters.Append cmd.CreateParameter("scenario", adVarChar, adParamInput, 4, "decline001")
End With
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
With rs
.CursorType = adOpenStatic
.CursorLocation = adUseClient
.LockType = adLockOptimistic
End With
Set rs = cmd.Execute
Cells(StartRow + 1, 1).CopyFromRecordset rs
rs.Close
conn.Close
End Sub
This does not work obviously, I get a run-time error '-2147217900 (80040e14): One or more errors occurred during processing of command.' So, OK.
I am looking for some guidance/advice on how to bring back that cursor into an ADODB.RecordSet. I don't think I have set up the output cursor correctly for "out_cur_data", but my searches online for any help have come up dry so far. Can any give me a basic working example to help me understand what I am doing wrong?
BTW... I do not have control of the stored procedure at all, it is from an external package.
Any help is really appreciated.
Thanks,
Doran
I think it should be this one:
With cmd
.Properties("PLSQLRSet") = TRUE
.ActiveConnection = conn
.CommandType = adCmdText
.CommandText = "{call their_package.get_product(?,?)}"
.NamedParameters = True
.Parameters.Append cmd.CreateParameter("rptid", adNumeric, adParamInput, 0, 98)
.Parameters.Append cmd.CreateParameter("scenario", adVarChar, adParamInput, 4, "decline001")
End With
...
Set rs = cmd.Execute
cmd.Properties("PLSQLRSet") = FALSE
Note:
Although their_package.get_product() takes three parameters, only two need to be bound because Ref cursor parameters are automatically bound by the provider.
For more information check Oracle documentation: Oracle Provider for OLE DB Developer's Guide - "Using OraOLEDB with Visual Basic"
I need to retrieve data from an Oracle Stored Procedure. The stored Procedure is as follows:
CREATE OR REPLACE PROCEDURE ATP_CONTRACT_SP
(
p_ContractNumber IN VARCHAR2,
p_ResultSet OUT ATPSP.cursorType
)
AS
BEGIN
OPEN p_ResultSet FOR
with t1 as (
select sc.c_ntp_no as ATP#, case when length(sc.c_proj_code) = 6
...
from agt),
mt2 as (
select * from mt union select * from modagt
order by 3, 1 desc)
select mt2.atp#, mt2.llw#, '' as School, mt2.c_cont_type, mt2.approved, mt2.phase, mt2.award, mt2.amendment,
mt2.totalaward, mt2.ATPApprvdOn, mt2.rfp, mt2.balance, mt2.ctd_rfp
from mt2;
END;
The Access Code is as follows:
Dim atpNumber As ADODB.Parameter, llwNumber As ADODB.Parameter, schoolString As ADODB.Parameter, _
contractTypeString As ADODB.Parameter, approvedBool As ADODB.Parameter, _
phaseString As ADODB.Parameter, awardNumber As ADODB.Parameter, _
amendmentNumber As ADODB.Parameter, totalAwardNumber As ADODB.Parameter, _
ATPApprovedOnDate As ADODB.Parameter, rfpNumber As ADODB.Parameter, _
balanceNumber As ADODB.Parameter, ctd_rfpString As ADODB.Parameter
Dim conn As ADODB.Connection
Dim connString As String
connString = "Driver={Microsoft ODBC for Oracle};DSN=xxx;UID=xxx;PWD=xxx;SERVER=xxx"
Dim rsCommand As ADODB.Command
Set rsCommand = New ADODB.Command
Set atpNumber = rsCommand.CreateParameter("atp#", adVarChar, adParamOutput, 20)
Set llwNumber = rsCommand.CreateParameter("llw#", adVarChar, adParamOutput, 20)
Set schoolString = rsCommand.CreateParameter("School", adVarChar, adParamOutput, 20, Null)
Set contractTypeString = rsCommand.CreateParameter("c_cont_type", adVarChar, adParamOutput, 20)
Set approvedBoolString = rsCommand.CreateParameter("approved", adVarChar, adParamOutput, 2)
Set phaseString = rsCommand.CreateParameter("phase", adVarChar, adParamOutput, 35)
Set awardNumber = rsCommand.CreateParameter("award", adNumeric, adParamOutput)
Set amendmentNumber = rsCommand.CreateParameter("amendment", adNumeric, adParamOutput)
Set totalAwardNumber = rsCommand.CreateParameter("totalaward", adNumeric, adParamOutput)
Set ATPApprovedOnDate = rsCommand.CreateParameter("ATPApprvdOn", adDate, adParamOutput)
Set rfpNumber = rsCommand.CreateParameter("rfp", adNumeric, adParamOutput)
Set balanceNumber = rsCommand.CreateParameter("balance", adNumeric, adParamOutput)
Set ctd_rfpString = rsCommand.CreateParameter("ctd_rfp", adVarChar, adParamOutput, 255)
rsCommand.Parameters.Append atpNumber
rsCommand.Parameters.Append llwNumber
rsCommand.Parameters.Append schoolString
rsCommand.Parameters.Append contractTypeString
rsCommand.Parameters.Append approvedBoolString
rsCommand.Parameters.Append phaseString
rsCommand.Parameters.Append awardNumber
rsCommand.Parameters.Append amendmentNumber
rsCommand.Parameters.Append totalAwardNumber
rsCommand.Parameters.Append ATPApprovedOnDate
rsCommand.Parameters.Append rfpNumber
rsCommand.Parameters.Append balanceNumber
rsCommand.Parameters.Append ctd_rfpString
Set rsRecords = rsCommand.Execute
On the rsCommand.Execute line there is an error message: Multiple-step OLEDB operation generated errors. I've been working on this for two days and need to get this done. And I'm interested in the technical challenge.
Where could I be going wrong?
Please alert me to any questions.
1 you never set the rsCommand properties to specify the Oracle Procedure
2 it returns a recordset, not a series of parameters
You need 1 Input Parameter p_contractnumber advarchar
You need 1 Output Parameter P_resultset