I'm a complete VBScript newbie and I am trying to execute a stored procedure and read the resultset. I have tried numerous different approaches using articles online but nothing works and I'm stumped. The database is SQL Server 2008 R2, the application is an off-the-shelf ERP system but I'm able to add my own code to it.
I can execute code by using:
connection.execute"insert into blah blah blah"
And I can read result set by using:
Set objRS = CreateObject("ADODB.Recordset")
objRS.Open "select a, b, c FROM blahblah", Connection, adOpenStatic, adLockBatchOptimistic, adCmdText
If objRS.EOF = False Then
a = objRS.Fields("a").Value
b = objRS.Fields("b").Value
c = objRS.Fields("c").Value
End If
objRS.Close
The stored procedure in question is in effect a select statement e.g.:
create procedure [dbname].[dbo].[sptestproc]
as
#Option1 Varchar(10) = NULL,
#Option2 Varchar(10) = NULL
AS
BEGIN
select first, second
from table1
where a = #option1 and b = #toption2
End
My code so far:
Dim sql
sql = "EXEC [dbname].[dbo].[sptestproc] '" & Opt1 & "','" & Opt2 & "'"
Set RS = CreateObject("ADODB.Recordset")
RS.Open sql, Connection, adOpenStatic, adLockBatchOptimistic, adCmdText
Do While Not RS.EOF
Call App.MessageBox("first",vbInformation,"Data updated")
Call App.MessageBox("second",vbInformation,"Data updated")
RS.MoveNext
Loop
But I cannot for the life of me get a procedure to execute and read the results.
Can anyone help?
Thanks
adCmdText would be for SQL query if you want to execute a stored procedure then you have to use adCmdStoredProc (value 4 instead)
EDIT:
'Set the connection
'...............
'Set the command
DIM cmd
SET cmd = Server.CreateObject("ADODB.Command")
SET cmd.ActiveConnection = Connection
'Set the record set
DIM RS
SET RS = Server.CreateObject("ADODB.recordset")
'Prepare the stored procedure
cmd.CommandText = "[dbo].[sptestproc]"
cmd.CommandType = 4 'adCmdStoredProc
cmd.Parameters("#Option1 ") = Opt1
cmd.Parameters("#Option2 ") = Opt2
'Execute the stored procedure
SET RS = cmd.Execute
SET cmd = Nothing
'You can now access the record set
if (not RS.EOF) THEN
first = RS("first")
second = RS("second")
end if
'dispose your objects
RS.Close
SET RS = Nothing
Connection.Close
SET Connection = Nothing
Connection.Execute "SET NOCOUNT ON"
Before
SET cmd.ActiveConnection = Connection
I went well.
Dim sql
Set RS = CreateObject("ADODB.Recordset")
Set cmd = CreateObject("ADODB.Command")
Set prm = cmd.CreateParameter("#option1", adVarChar, adParamInput, , Opt1)
cmd.Parameters.Append prm
Set prm = cmd.CreateParameter("#option2", adVarChar, adParamInput, , Opt2)
cmd.Parameters.Append prm
cmd.CommandText = "[dbname].[dbo].[sptestproc]"
Set Com.ActiveConnection = Connection
'Connection must be opend already
RS.Open cmd, , adOpenStatic, adLockBatchOptimistic
Do While Not RS.EOF
Call App.MessageBox("first",vbInformation,"Data updated")
Call App.MessageBox("second",vbInformation,"Data updated")
RS.MoveNext
Loop
Related
I need to call Oracle package procedure from VBScript (from PowerDesigner app). It is 64-bit application so i am using Oracle 64-bit ODBC driver (Oracle client 12.1.0.2).
The job should be done with following code, which runs without any error but output values are empty:
Const ORAUser = "****"
Const ORAPass = "****"
Const ORASchema = "****"
Const ORAInst = "****"
Const ORADRV = "Oracle in OraClient12Home1"
Const ADO_CMD_STORED_PROC = 4
Dim Conn, ConnString, CmdStoredProc
Set Conn = CreateObject("ADODB.Connection")
ConnString = "Driver={" + ORADRV + "};Dbq=" + ORAInst + ";Uid=" + ORAUser + ";Pwd=" + ORAPass + ";"
Conn.Open ConnString
Set CmdStoredProc = CreateObject("ADODB.Command")
With CmdStoredProc
Set .ActiveConnection = Conn
.CommandText = ORASchema & ".PDLOCKS_ADMIN.VBS_TEST"
.CommandType = ADO_CMD_STORED_PROC
.Parameters.Append CmdStoredProc.CreateParameter("i_input_num", 5, 1, 0, 1)
.Parameters.Append CmdStoredProc.CreateParameter("i_input_vchar", 200, 1, 4000, "1")
.Parameters.Append CmdStoredProc.CreateParameter("o_output_num", 5, 2, 0)
.Parameters.Append CmdStoredProc.CreateParameter("o_output_vchar", 200, 2, 4000)
.Execute
Output .Parameters("o_output_num").Value ' EMPTY :-(
Output .Parameters(2) ' EMPTY :-(
End With
Conn.Close
Set Conn = Nothing
Set CmdStoredProc = Nothing
In Oracle database package procedure is everything processed correctly and input and output parameters are saved into table TEST:
PROCEDURE VBS_TEST (
i_input_num in number
,i_input_vchar in varchar2
,o_output_num out number
,o_output_vchar out varchar2
)
IS
BEGIN
insert into test values (to_char(i_input_num) || i_input_vchar);
o_output_num := i_input_num + 1;
o_output_vchar := i_input_vchar || '1';
insert into test values (to_char(o_output_num) || o_output_vchar);
commit;
END;
select banner
from v$version
;
BANNER
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
PL/SQL Release 12.1.0.2.0 - Production
"CORE 12.1.0.2.0 Production"
TNS for Solaris: Version 12.1.0.2.0 - Production
NLSRTL Version 12.1.0.2.0 - Production
With its 12c release, Oracle has added the functionality to allow the declaration of Pl/SQL functions directly at the top of an SQL statement (see https://oracle-base.com/articles/12c/with-clause-enhancements-12cr1)
This can be quite a handy feature, esp. on projects where you need to pull data from DBs with user rights limited to SELECT statements.
The following (obviously simplified) query runs fine in Oracle SQL Developer:
with
function add_string(p_string in varchar2) return varchar2
is
--Function to add a string
l_buffer varchar2(32767);
begin
l_buffer := p_string || ' works!';
--
return l_buffer;
--
end ;
--
select add_string('Yes, it') as outVal
from dual
;
---------
OUTVAL
Yes, it works!
Now, I am trying to load the result set of a query based on the same principle into an ADODB Recordset in MS-Access 2007. I am aware that ADO does not handle queries starting with a WITH clause seamlessly (see, e.g. Why can't I do a "with x as (...)" with ADODB and Oracle?). The way I usually get around this problem is to enclose the query in a SELECT block, like this:
select hey_yo
from (
with sub as (
select 'hey' as hey
from dual
)
select hey || ' yo!' as hey_yo
from sub
)
;
---------
HEY_YO
hey yo!
Unfortunately, this does not seem to be legal syntax in Oracle when dealing with functions in the WITH clause:
select *
from (
with
function add_string(p_string in varchar2) return varchar2
is
--Function to add a string
l_buffer varchar2(32767);
begin
l_buffer := p_string || ' works!';
--
return l_buffer;
--
end ;
--
select add_string('Yes, it') as outVal
from dual
)
;
---------
PLS-00103: Encountered the symbol ")" when expecting one of the following:
. , # ; for <an identifier>
<a double-quoted delimited-identifier> group having intersect
minus order partition start subpartition union where connect
sample
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
Here's the sub I'm trying to run in VBA:
Sub TestSub()
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
'Connection details
Dim strHostName As String
Dim nPortNum As Integer
Dim strUser As String
Dim strPassword As String
Dim strServiceName As String
Dim strConnection As String
Dim strSQL As String
Set conn = New ADODB.Connection
'[... set credentials ...]
'Open Connection
With conn
.ConnectionString = "Provider=MSDAORA;" & _
"Data Source=(DESCRIPTION=(ADDRESS_LIST=" & _
"(ADDRESS=(PROTOCOL=TCP)(HOST=" & strHostName & ")(PORT=" & nPortNum & ")))(CONNECT_DATA=(SERVICE_NAME=" & strServiceName & ")));" & _
"User ID=" & strUser & ";Password=" & strPassword & ";"
.Open
End With
Set rs = New ADODB.Recordset
strSQL = "WITH FUNCTION add_string(p_string IN VARCHAR2) RETURN VARCHAR2 IS l_buffer VARCHAR2(32767); BEGIN l_buffer := p_string || ' works!'; RETURN l_buffer; END ; SELECT add_string('Yes, it') AS outval FROM dual"
rs.Open strSQL, conn, adOpenStatic, adLockReadOnly
'[... do stuff with data ...]
rs.MoveFirst
Debug.Print rs.Fields(0).Value
rs.Close
Set rs = Nothing
conn.Close
Set conn = Nothing
End Sub
Any ideas how to get around this problem? (Unfortunately, compiling the function in the DB is not an option for this particular project).
Update:
I should mention the error I get when running the VBA code:
Run-Time error 3704: Operation is not allowed when the object is
closed.
at rs.MoveFirst
Use the "Oracle Provider for OLE DB" instead of "Microsoft OLE DB Provider for Oracle". Oracle provider can be downloaded from here: 32-bit Oracle Data Access Components (ODAC) and NuGet Downloads
The Microsoft provider has been deprecated for many years, it is not further developed and should not be used anymore. Current release of Oracle provider is 12.1, i.e. it should support also new Oracle 12c features.
Connection string would be Provider=OraOLEDB.Oracle; ... instead of Provider=MSDAORA;...
Unfortunately I can't test the following because I have only an Oracle 11 at my disposal here.
In theory it should work. But you should use a ADODB.Command to send the SQL as it is, straight away to Oracle
Try this :
Dim strConnection As String
Dim strSQL As String
Dim cmdQuery As ADODB.Command
Set conn = New ADODB.Connection
'[... set credentials ...]
'Open Connection
With conn
.ConnectionString = "Provider=MSDAORA;" & _
"Data Source=(DESCRIPTION=(ADDRESS_LIST=" & _
"(ADDRESS=(PROTOCOL=TCP)(HOST=" & strHostName & ")(PORT=" & nPortNum & ")))(CONNECT_DATA=(SERVICE_NAME=" & strServiceName & ")));" & _
"User ID=" & strUser & ";Password=" & strPassword & ";"
.Open
End With
Set rs = New ADODB.Recordset
strSQL = "WITH FUNCTION add_string(p_string IN VARCHAR2) RETURN VARCHAR2 IS l_buffer VARCHAR2(32767); BEGIN l_buffer := p_string || ' works!'; RETURN l_buffer; END ; SELECT add_string('Yes, it') AS outval FROM dual"
Set cmdQuery = New ADODB.Command
cmdQuery.ActiveConnection = conn
cmdQuery.CommandText = strSQL
With rs
.LockType = adLockPessimistic
.CursorType = adUseClient
.CursorLocation = adUseClient
.Open cmdQuery
End With
'[... do stuff with data ...]
I've never worked with Stored Procedures, so I'm completely lost. One of our DB admin created a SP in Oracle that accepts three variables, and has one OUT variable. How do I see the results of the procedure once I call it?
DECLARE
v_srch_sw VARCHAR2(1);
v_srch_crit VARCHAR2(20);
v_ssn_last_four VARCHAR2(4);
v_ivr_data VARCHAR2(4000);
BEGIN
DBMS_OUTPUT.enable(buffer_size => NULL);
v_srch_sw := 'A';
v_srch_crit := '1234567890';
v_ssn_last_four := '1234';
schemaname.sp_name_010(v_srch_sw
,v_srch_crit
,v_ssn_last_four
,v_ivr_data);
DBMS_OUTPUT.PUT_LINE(v_ivr_data);
END;
/
Note: The DBMS_OUTPUT.PUT_LINE returns the results as a message, but not an actual result. For example, when I put this code in MS Access '07 as a pass-through query, no results are returned. How do I get this to return the results just like normal SELECT query?
How do I get this to return the results just like normal SELECT query?
First, be aware that the code in the question is not the stored procedure, it is PL/SQL code to invoke the stored procedure and display the results in Oracle.
Second, AFAIK there is no way to invoke that stored procedure from Access "like a normal SELECT query" because the stored procedure does not return a result set. Instead, it returns its value as an output parameter.
However, you can create a Function in VBA that calls the stored procedure and returns the result. The following example works with SQL Server, but the code for Oracle should be very similar. (For example the parameter names might be slightly different, possibly omitting the # prefix.)
Option Compare Database
Option Explicit
Public Function Call_sp_name_010(v_srch_sw As String, v_srch_crit As String, v_ssn_last_four As String) As Variant
Const linkedTableName = "dbo_Clients" ' an existing ODBC linked table
Dim cdb As DAO.Database
Set cdb = CurrentDb
Dim con As New ADODB.Connection
con.Open "DSN=" & Mid(cdb.TableDefs(linkedTableName).Connect, 5) ' omit "ODBC;" prefix
Dim cmd As New ADODB.Command
cmd.ActiveConnection = con
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "schemaname.sp_name_010"
cmd.Parameters.Append cmd.CreateParameter("#v_srch_sw", adVarChar, adParamInput, 1)
cmd.Parameters.Append cmd.CreateParameter("#v_srch_crit", adVarChar, adParamInput, 20)
cmd.Parameters.Append cmd.CreateParameter("#v_ssn_last_four", adVarChar, adParamInput, 4)
cmd.Parameters.Append cmd.CreateParameter("#v_ivr_data", adVarChar, adParamOutput, 4000)
cmd.Parameters("#v_srch_sw").Value = v_srch_sw
cmd.Parameters("#v_srch_crit").Value = v_srch_crit
cmd.Parameters("#v_ssn_last_four").Value = v_ssn_last_four
cmd.Execute
' function returns output parameter value
Call_sp_name_010 = cmd.Parameters("#v_ivr_data").Value
Set cmd = Nothing
con.Close
Set con = Nothing
Set cmd = Nothing
End Function
Now, if necessary, you can use that user-defined function in an Access query.
I'm getting an error in Classic ASP when give oracle date to oracle function in asp. My code:
dim startDate, endDate
startDate = rs1.fields("oraDate1") 'field is oracle field. Gets with oracle to_char('30.10.203','dd/mm/yyyy')
endDate = rs1.fields("oraDate2") 'oraDate2 is like oraDate1
if IsDate(startDate) Then
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = conn
cmd.CommandText = "find_business_day" 'oracle function
cmd.CommandType = 4
dim date1, date2
set date1 = cmd.CreateParameter("start_date",135,1)
cmd.Parameters.Append date1
date1.value = startDate
set date2 = cmd.CreateParameter("end_Date", 135, 1)
cmd.Parameters.Append date2
date2.value = endDate
cmd.Execute
The error is on the cmd.Execute line, the error message is:
Microsoft OLE DB Provider for ODBC Drivers hata '80004005'
[Microsoft][ODBC driver for Oracle]Invalid parameter type
My oracle function:
CREATE OR REPLACE FUNCTION find_business_day (my_trh1 date,my_trh2 date) return number is
my_isgunu number(2);
begin
select count(*) into my_isgunu from takvim where tatil=1 and tarih between my_trh1 and my_trh2;
Return(my_isgunu);
exception
When others then return(0);
end find_business_day;
/
I solve this problem with change oracle function parameter types.
Here is my solution:
dim startDate, endDate
startDate = rs1.fields("mail_gon_trh")
endDate = rs1.fields("olur_trh")
if IsDate(startDate)
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = conn
cmd.CommandText = "find_business_day"
cmd.CommandType = 4
set returnval = cmd.CreateParameter("my_isgunu",131,4,100)
cmd.Parameters.Append returnval
set date1 = cmd.CreateParameter("my_trh1",201,1,100)
cmd.Parameters.Append date1
cmd.parameters(1).value = startDate
set date2 = cmd.CreateParameter("my_trh2", 201, 1,100)
cmd.Parameters.Append date2
cmd.parameters(2).value = endDate
cmd.Execute
result = cmd.Parameters(0)
end if
My oracle function:
CREATE OR REPLACE FUNCTION TUBORTAK.ISGUNU_BUL_TRH2 (my_trh1 varchar,my_trh2 varchar) return number is
my_isgunu number(3);
my_trh1_date date;
my_trh2_date date;
begin
my_trh1_date:=to_date(my_trh1,'dd/mm/yyyy');
my_trh2_date:=to_date(my_trh2,'dd/mm/yyyy');
select count(*) into my_isgunu from takvim where tatil=1 and tarih between my_trh1_date and my_trh2_date;
Return(my_isgunu);
exception
When others then return(0);
end ISGUNU_BUL_TRH2;
/
I am trying to call a PL/SQL block with ADO and VBA, but I can't pass input and/or output bind variables (probably aka parameters).
dim cn as ADODB.connection
' ... open connection ...
dim plsql as string
plsql = "declare"
plsql = plsql & " num_in number := ?;"
plsql = plsql & " num_out number; "
plsql = plsql & "begin"
plsql = plsql & " num_out := num_in * 5;"
plsql = plsql & " ? := num_out;"
plsql = plsql & "end;"
dim cm as ADODB.command
set cm = new ADODB.command
set cm.activeConnection = cn
cm.commandText = plsql
cm.commandType = adCmdText
cm.parameters.append cm.createParameter(, adDouble, adParamInput,, 5)
cm.parameters.append cm.createParameter(, adDouble, adParamOutput )
cm.execute ' FAILS HERE
msgBox(cm.parameters(2))
The snippet above fails at the cm.execute line with an ORA-01008: not all variables bound
I'd appreciate any help towards a solution for my problem.
It seems as though the statement cannot start with a declare. (Thanks to Thomas Jones-Low for his valuable comment).
So, the statement must be enclosed in another begin .. end block:
' additional begin so that the statement does not start with a declare:
plsql = "begin "
plsql = plsql & "declare"
plsql = plsql & " num_in number := ?;"
plsql = plsql & " num_out number; "
plsql = plsql & "begin"
plsql = plsql & " num_out := num_in * 5;"
plsql = plsql & " ? := num_out;"
plsql = plsql & "end;"
' closing the additional begin:
plsql = plsql & "end;"
Now, it works as expected.