Calling an oracle stored procedure with no parameters ADODB - oracle

I have not found anywhere on how to call an Oracle stored procedure using ADODB from Excel where the stored procedure has no input parameters.
Fake example to illustrate lack of input parameters:
CREATE OR REPLACE PROCEDURE Get_Data
(OUTPUT OUT SYS_REFCURSOR) IS
******************************************************************************/
BEGIN
OPEN OUTPUT FOR
SELECT DISTINCT
B.ITEM_ID
B.ITEM_DESC
FROM ITEM_FILE B
WHERE ITEM_ID IS NOT NULL
ORDER BY B.ITEM_ID
;
END Get_Data;
/
Oh, and the stored procedure is required because we don't want to give users SQL access to create whatever SQL they want.
Is this even possible? And if so, what kind of code would it take to call it?
Thanks,
Dan

Transform your procedure to a function:
CREATE OR REPLACE FUNCTION Get_Data RETURN SYS_REFCURSOR IS
res SYS_REFCURSOR;
BEGIN
OPEN OUTPUT FOR
SELECT DISTINCT
B.ITEM_ID
B.ITEM_DESC
FROM ITEM_FILE B
WHERE ITEM_ID IS NOT NULL
ORDER BY B.ITEM_ID;
RETURN res;
END Get_Data;
/
Call in VBA would be as this:
cmd.CommandText = "{CALL Get_Data()}"
cmd.Properties("PLSQLRSet") = True
Set Rst1 = cmd.Execute
cmd.Properties("PLSQLRSet") = False
Note, by default an OUT parameters are used like this:
cmd.Parameters.Append cmd.CreateParameter("OUTPUT", adVarChar, adParamOutput, 100)
However, for RefCursor parameters you must not declare them with cmd.Parameters.Append.
Have a look at Provider for OLE DB Developer's Guide, it contains several examples. Chapter Stored Procedures and Functions Returning Rowsets should be the most relevant for you.

Related

Creating Oracle PL/SQL Stored procedure

I'm trying to convert the SQL Query to Oracle PL/SQL stored procedure.
Here is the query:
select * from table1 where DATE = " + s1 + " and TYPE='" + ty + "' and NAME='"+nm+"' Order by TYPE DEsc;
Here is the Stored Procedure:
CREATE PROCEDURE procedure1
(
s1 IN DATE,
ty IN CHAR DEFAULT 2,
nm IN VARCHAR2 DEFAULT 64
)
IS
d table1.DATE%TYPE;
C table1.TYPE%TYPE;
S table1.NAME%TYPE;
CURSOR tb IS select DATE,TYPE,NAME INTO d,c,s from table1;
BEGIN
FOR i IN tb
LOOP
DBMS_OUTPUT.PUT_LINE('DATE' ||i.DATE);
DBMS_OUTPUT.PUT_LINE('TYPE' ||i.TYPE);
DBMS_OUTPUT.PUT_LINE('NAME' ||i.NAME);
END LOOP;
END procedure1;
I do not see any output after Executing Stored procedure. I'm not sure if I have created the stored procedure correctly.
"I do not see any output after Executing Stored procedure"
Your "output" is DBMS_OUTPUT which is for displaying text to a screen. However, by default it writes the text to a buffer, and we need to enable the output to see the contents of the buffer.
How to do this varies depending on which client you're using. In SQL*Plus it's
SQL> set serveroutput on
In an IDE like TOAD, PLSQL Developer or Oracle SQL Developer there's a separate DBMS_OUTPUT tab: click on the tab and enable output (there's a button) - or set Preferences to always have it on.
DBMS_OUTPUT is rarely a useful means for returning data in an actual application. The normal approach is to use a Ref Cursor, which maps to JDBC and ODBC ResultSet classes. Something like this:
CREATE OR REPLACE PROCEDURE procedure1
(
s1 IN DATE,
ty IN CHAR DEFAULT 2,
nm IN VARCHAR2 DEFAULT 64,
rc out sys_refcursor
)
IS
BEGIN
open rc for
select * from table1
where d = s1
and c = ty
and s = nm;
END procedure1;
/
Incidentally, your parameters are defined with string datatypes but the defaults are numeric values. Please don't get into bad habits. Strong datatyping is a key defence against data corruption and broken code, so always use the correct data type.
try this;
CREATE PROCEDURE PROCEDURE1 (
S1 IN DATE,
TY IN CHAR DEFAULT 2,
NM IN VARCHAR2 DEFAULT 64
)
IS
BEGIN
FOR I IN (SELECT DATE, TYPE, NAME FROM TABLE1)--Easier way to use cursor
LOOP
DBMS_OUTPUT.PUT_LINE ('DATE' || I.DATE);
DBMS_OUTPUT.PUT_LINE ('TYPE' || I.TYPE);
DBMS_OUTPUT.PUT_LINE ('NAME' || I.NAME);
END LOOP;
END PROCEDURE1;
by executing this you only created the procedure and stored it in db, you need to call it and turn on system output to see the output. like this:
set serveroutput on;
begin
PROCEDURE1(null, null, null);
end;
What environment are using to compile your code? You should certainly be seeing some immediate feedback.
Note that in most environments, though, you need to do a little more than you did before.
The final ";" in your code is part of PL/SQL. It does not trigger execution of your DDL. Generally you should do this:
CREATE OR REPLACE PROCEDURE myproc
IS
BEGIN
...
END myproc;
/
And that "/" will submit your statement for execution.

Oracle equivalent of stored procedure that returns an inline table?

Example in T-SQL (SQL Server - taken from here):
CREATE PROC proc_authors
#au_lname VARCHAR(40)
AS
SELECT
au_id, au_fname, au_lname, city, state
FROM authors
WHERE au_lname = #au_lname
go
Is it possible in Oracle to create a stored procedure that returns an inline table (without declaring a type - like the above)? If not, what would be the closest alternative? i.e. declare inline type, then use it. The idea is to minimize number of DB permissions that are granted.
Please include sample code as part of your answer.
Reasoning behind using stored procedure vs function - we have legacy software that can only execute stored procedures, or raw queries. It appears that only stored procedures in there have support for parameterized execution, which is what we are after.
try this with ref cursor
PROCEDURE proc_get_tada(ip_user IN VARCHAR2,
op_error_code OUT NUMBER,
op_cursor OUT SYS_REFCURSOR,) AS
BEGIN
OPEN op_cursor FOR
SELECT * FROM your_table yt where yt.user = ip_user;
EXCEPTION
WHEN OTHERS THEN
op_error_code := -1;
END proc_get_tada;
you will get collection of all data from you table you can iterate in java or calling program.
Maybe you are searching for something like this:
create table author
(
au_id number,
au_name varchar2(100)
);
insert into author (au_id, au_name) values(1, 'ME');
create or replace function getAuthor(auName varchar2)
return author%rowtype
is
retval author%rowtype;
begin
select * into retval from author where au_name=auName;
return retval;
end;
declare
auth author%rowtype;
begin
auth := getAuthor('ME');
dbms_output.put_line(auth.au_id);
end;

Oracle Stored Procedure Return Recordset with Field Names

I am new to Oracle and Stored Procedures. I just would like to know if its possible, like in SQL Server, to return a recordset with Field Names to an extern program. I read some documentations but I'm not sure if I'm on the right track. When I use Sys_Refcursor I can only return one Field and not as many as I would like to.
I need to return multiple Field Names and I have one input parameter.
In the documentation of the program, i have an example for SQL Server and I would like to have the same for my Oracle Stored Procedure:
Use
Go
Set Ansi_Nulls ON
Go
Alter Procedure
#InputLocation Varchar(255)
As
Begin
Set Nocount On;
select FirstName as '#FirstName', Company as '#Company' from dbo.company where Location = #InputLocation
End
Are there any suggestions how I can do that? If you need some additional informations just let me know. Thanks.
/edit:
My sample Code (without using the Input Parameter in the first step, just for generating Output to see if it works):
create or replace
PROCEDURE TEST_PROZEDUR1 (
Input_Location IN Varchar2,
First_Name OUT SYS_Refcursor,
Company OUT Sys_Refcursor) IS
BEGIN
open First_Name For Select FirstName from dbo.company;
open Company For Select Company from dbo.company;
END TEST_PROZEDUR1;
The programming models used for PL/SQL and TSQL are different. Where you might return a recordset in TSQL, in PL/SQL you would return a cursor. A cursor is just a pointer to an SQL statement which is opened and can be read. It is not limited to returning a single column. Roughly, the PL/SQL equivalent of your TSQL procedure above would be something like:
CREATE OR REPLACE FUNCTION GET_INPUT_LOCATION(pinInput_location IN VARCHAR2(255))
RETURN SYS_REFCURSOR
IS
cCursor SYS_REFCURSOR;
BEGIN
OPEN cCursor FOR
SELECT FIRSTNAME,
COMPANY
FROM COMPANY
WHERE LOCATION = pinInput_location;
RETURN cCursor;
END GET_INPUT_LOCATION;
The caller would then invoke this function as:
DECLARE
cCursor SYS_REFCURSOR;
strFirstname COMPANY.FIRSTNAME%TYPE;
strCompany COMPANY.COMPANY%TYPE;
BEGIN
cCursor := GET_INPUT_LOCATION('SOMEWHERE OVER THE RAINBOW, INC.');
FETCH cCursor
INTO strFirstname,
strCompany;
CLOSE cCursor;
END;
However, I probably wouldn't code it this way. If COMPANY.LOCATION is unique then you're going to a lot of trouble to return a cursor which the caller will need to remember to close when they're done with it, which they may forget to do. Instead, I'd just return the FIRSTNAME and COMPANY fields using output parameters; e.g.
CREATE OR REPLACE PROCEDURE GET_INPUT_LOCATION
(pinInput_location IN VARCHAR2(255),
poutFirst_name OUT COMPANY.FIRSTNAME%TYPE,
poutCompany OUT COMPANY.COMPANY%TYPE)
IS
cCursor SYS_REFCURSOR;
BEGIN
SELECT FIRSTNAME,
COMPANY
INTO poutFirst_name,
poutCompany
FROM COMPANY
WHERE LOCATION = pinInput_location;
END GET_INPUT_LOCATION;
Share and enjoy.

Oracle Stored Procedure not Returning Results

My Oracle Stored Procedure does not return any results. I have tested the query outside the SPROC and it seems to return values. I have a feeling it has something to do with how I'm passing the sample and test parameters - because if I hardcode the sampleNumber and testNumber parameters in the Stored Proc, the results are returned correctly. I have pasted the Procedure and the PLSQL Declaration. I am very new to writing Oracle Procedures and any help will be greatly appreciated. Thank you.
CREATE OR REPLACE PROCEDURE TESTANALYSIS
(vOrderNumber IN VARCHAR2
, vTestNumber IN NUMBER
, vSampleNumber IN NUMBER
)
AS
anVar VARCHAR2(50) := NULL;
BEGIN
SELECT T.ANALYSIS INTO anVar FROM TEST T JOIN SAMPLE S
ON T.SAMPLE_NUMBER = S.SAMPLE_NUMBER
WHERE T.TEST_NUMBER = vTestNumber
AND S.SAMPLE_NUMBER = vSampleNumber
AND S.ORDER_NUM = vOrderNumber;
dbms_output.put_line(anVar);
END TESTANALYSIS;
--PL SQL Call
SET SERVEROUTPUT ON
EXEC TESTANALYSIS('4200010061', 720000050516, 14789)
/

Accessing Data from Stored Procedure using CallableStatement

I have written a Stored Procedure as shown , which will be responsible to give the
list of the EMployee Numbers
create or replace procedure
kiran
as
CURSOR cur is select * from emp;
TEMPCUR cur%rowtype;
begin
open cur;
loop
fetch cur into TEMPCUR;
DBMS_OUTPUT.PUT_LINE(TEMPCUR.empno);
exit when cur%NOTFOUND;
end loop;
close cur;
end;
/
Please tell me how can i retrive this values from a JDBC program
callableStatement = dbConnection.prepareCall(kiran);
// Please help need logic here
You cannot do it with exactly the procedure you listed, but you can easily do it if you change your procedure to return ref cursor. There are numerous examples of doing that. Here's the first one from Google search results: http://www.enterprisedt.com/publications/oracle/result_set.html .
EDIT:
Based on the changed stored procedure definition, the JDBC command would look like this:
{? = call test}
You will have to create a CallableStatement with this command, register an out parameter of type Oracle REF CURSOR and execute it. You will get your results as the first output parameter:
ResultSet rs = (ResultSet)stmt.getObject(1);
Here's how you do it. Remember, the last parameter in my example is actually declared in the PL/SQL procedure as an "OUT" parameter, e.g. the value you want to return in the form of a parameter):
conn --- is the connection object
cstmt --- this is a callablestatement
cstmt = conn.getNewCallableStatement("{call MY_PLSQL_PACKAGE.MY_PROC(?,?,?)}");
cstmt.setString(1, stringOutput1);
cstmt.setString(2, stringOutput2);
cstmt.registerOutParameter(3, OracleTypes.CURSOR);
cstmt.execute;

Resources