If I write a simple function doSomething, I can get its result by executing :
select doSomething() from dual;
But, if I wish to call a procedure that has an OUT cursor being passed to it (along with another int parameter), how do I call that procedure inside a query and access the result of the cursor ?
Calling it inside a query is not compulsory.. its just that I want to access the results of that procedure
You can create a procedure like
CREATE OR REPLACE PROCEDURE your_procedure(out_cursor OUT sys_refcursor)
IS
BEGIN
OPEN out_cursor FOR
SELECT employee_name
FROM employees;
END;
/
Once you create your procedure wrap the procedure in a function which returns a cursor like the following
CREATE OR REPLACE FUNCTION your_function
RETURN sys_refcursor
AS
o_param sys_refcursor;
BEGIN
o_param := NULL;
your_procedure(o_param);
RETURN o_param;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
-- raise
WHEN OTHERS
THEN
-- raise
END your_function;
/
To see the results from sql do as
select your_function from dual;
Update 1
To see result in SQL Developer
Step 1
Double click on your results in SQL Developer
[Results][1]
Step 2 Single Click on the button with dots. That will pop up the values
[Grid][2]
You can Do Something Like This
select doSomething(cursor (select int_col from your_table)) colname from dual
Hope this Help
Related
I keep getting the "SELECT query has no destination for result data" error upon calling this test procedure. What am I doing wrong? I did try adding the RETURN() command prior to SELECT statement but that didn't work either.
CREATE OR REPLACE PROCEDURE SchemaName.SP_Testing_Creating_Procedure (OUT ColumnName VARCHAR(9))
AS $$
BEGIN
SELECT TOP 10 ColumnName FROM SchemaName.TableName where ColumnName is not null;
END;
$$
LANGUAGE plpgsql;
CALL SchemaName.SP_Testing_Creating_Procedure();
As John mentioned you need to put the result into OUT column, examples of using IN, OUT and INOUT parameters you can find here
But if you need to return a few rows as a result, you have to use refcursor
as it's described here
CREATE OR REPLACE PROCEDURE SchemaName.SP_Testing_Creating_Procedure (INOUT result refcursor)
AS $$
BEGIN
OPEN result FOR
SELECT TOP 10 ColumnName
FROM SchemaName.TableName
WHERE ColumnName IS NOT null;
END;
$$
LANGUAGE plpgsql;
Then you can call the stored procedure in a transaction
BEGIN;
CALL logs.SP_Testing_Creating_Procedure('mycursor');
FETCH ALL FROM mycursor;
COMMIT;
another option is temp table which is also described in the above doc
Your procedure is running a SELECT command, but it is not doing anything with the results.
If your intention was to return a result set, you will need to put data in the OUT column.
See: Returning a result set - Amazon Redshift
I have a function my_funct(param1,param2) returning a SELECT QUERY as a text, I usually C/c the result, remove quotes, then run it.
How can execute the returned text in a query that call the function ?
I expect something like this:
SELECT resultOf( myfunct('foo','bar'))
with no extra columnname/type to declare. If such function does not exits built-in, let's create it, I don't mind.
If I understood correctly you want
Call a function returning a select query as text
Run that query to get the result.
Number and type of columns are dynamic
1. Using Do Block:
DO
$$
declare
ref_cursor refcursor:='mycursor';
begin
open ref_cursor for execute (select * from my_funct('foo','bar')) ;
end;
$$;
--Fetch all data from cursor
Fetch all from mycursor;
2. Using Function returning refcursor:
You can create a function like below:
create function my_funct1(param1 text) returns refcursor as
$$
declare
ref_cursor refcursor:='mycursor';
begin
open ref_cursor for execute param1;
return ref_cursor;
end;
$$
language plpgsql
To call above function use following code:
begin ;
select my_funct1((select * from my_funct('foo','bar')) );
fetch all from mycursor;
commit;
DEMO
Example i have a stored pl/sql
CREATE OR REPLACE PROCEDURE number( test in NUMBER )
........
// rest of code
isn't possible that i don't want run this execute
execute number(2);
i want run with
select * from number(2);
isn't possible to run stored pl/sql script with select statement to call the function instead of execute?
You can't execute a PROCEDURE from SQL; however, you can execute a FUNCTION from SQL.
First, redefine NUMBER as a FUNCTION:
CREATE OR REPLACE FUNCTION NUMBER(pTest IN NUMBER) RETURN NUMBER IS
someValue NUMBER := pTest * 100;
BEGIN
-- whatever
RETURN someValue;
END;
Then execute it from a SELECT statement as
SELECT NUMBER(2) FROM DUAL;
Share and enjoy.
I have a query and i have to put it in a stored procedure but when I call the stored procedure it doesn´t return anything;
This is my query:
select * from mdc_cat_parametros where param_llave='SMTP_SERVER';
When I execute the query it returns one row but the stored procedure doesn´t.
This is my stored procedure:
CREATE OR REPLACE PROCEDURE MDC_UTIL_PROCEDURE
AS
RT MDC_CAT_PARAMETROS%ROWTYPE;
BEGIN
SELECT * INTO RT FROM MDC_CAT_PARAMETROS WHERE PARAM_LLAVE='SMTP_SERVER';
END MDC_UTIL_PROCEDURE;
I call the stored procedure:
EXECUTE MDC_UTIL_PROCEDURE;
The stored procedure is populating RT but you then need to select out of it:
CREATE OR REPLACE PROCEDURE MDC_UTIL_PROCEDURE (results OUT SYS_REFCURSOR)
AS
RT MDC_CAT_PARAMETROS%ROWTYPE;
BEGIN
SELECT * INTO RT FROM MDC_CAT_PARAMETROS WHERE PARAM_LLAVE='SMTP_SERVER';
OPEN results FOR SELECT * FROM RT;
END MDC_UTIL_PROCEDURE;
or you could simplify it to get rid of the RT variable:
CREATE OR REPLACE PROCEDURE MDC_UTIL_PROCEDURE (results OUT SYS_REFCURSOR)
AS
BEGIN
OPEN results FOR
SELECT * FROM MDC_CAT_PARAMETROS WHERE PARAM_LLAVE='SMTP_SERVER';
END MDC_UTIL_PROCEDURE;
Your procedure is just fetching the result set into a local variable in the procedure. When the procedure exits, the variable is no longer in scope. If you want to return data from a select, you need to use a ref cursor. Here is a link to some good examples
I'm attempting to write a stored proc that takes in a number, n, and returns the first n results for a given query, exclusively locking those n rows. I'm a little new to SQL and I'm having a bit of difficulty matching data types correctly.
My package spec looks like this:
PACKAGE package IS
Type out_result_type is REF CURSOR;
PROCEDURE stored_proc
(in_n IN NUMBER DEFAULT 10,
out_list IN OUT out_result_type);
I then define the cursor in the procedure body, like so:
CURSOR OUT_RESULT_TYPE IS
SELECT a.id
FROM schema.table a
WHERE (some conditions) AND rownum <= in_n;
A bit later on I then try to extract the results of the cursor into the output variable:
OPEN OUT_RESULT_TYPE;
FETCH OUT_RESULT_TYPE INTO out_list; -- error on this line
CLOSE OUT_RESULT_TYPE;
But alas this code doesn't compile; oracle complains that out_list has already been defined with a conflicting data type. Any idea how I can resolve this issue? It's driving me crazy!
Thanks in advance.
CREATE OR REPLACE PACKAGE pkg_test
AS
TYPE tt_cur IS REF CURSOR;
PROCEDURE prc_cur (retval OUT tt_cur);
END;
CREATE OR REPLACE PACKAGE BODY pkg_test
AS
PROCEDURE prc_cur (retval OUT tt_cur)
AS
BEGIN
OPEN retval
FOR
SELECT *
FROM dual;
END;
END;
If you want to lock, use:
CREATE OR REPLACE PACKAGE BODY pkg_test
AS
PROCEDURE prc_cur (retval OUT tt_cur)
AS
BEGIN
OPEN retval
FOR
SELECT a.id
FROM schema.table a
WHERE (some conditions)
AND rownum <= in_n
ORDER BY
column
-- Never forget ORDER BY!
FOR UPDATE;
END;
END;
Two remarks:
A cursor doesn't lock.
You don't have to do Type out_result_type is REF CURSOR;, use default type sys_refcursor. See here: Oracle - How to have an out ref cursor parameter in a stored procedure?
Your out_list must be of wrong type. Consider (script run on 10.2.0.3):
CREATE TABLE t AS SELECT ROWNUM ID FROM all_objects WHERE ROWNUM <= 100;
CREATE OR REPLACE PACKAGE cursor_pck AS
TYPE out_result_type is REF CURSOR;
PROCEDURE stored_proc (p_in IN NUMBER DEFAULT 10,
p_out_list IN OUT out_result_type);
END cursor_pck;
/
If you want to select and lock the rows at the same time you would use the FOR UPDATE clause:
CREATE OR REPLACE PACKAGE BODY cursor_pck AS
PROCEDURE stored_proc (p_in IN NUMBER DEFAULT 10,
p_out_list IN OUT out_result_type) IS
BEGIN
OPEN p_out_list FOR SELECT a.id FROM t a WHERE ROWNUM <= p_in FOR UPDATE;
END stored_proc;
END cursor_pck;
/
With the following setup, you will call the procedure like this:
SQL> SET SERVEROUTPUT ON;
SQL> DECLARE
2 l_cursor cursor_pck.out_result_type;
3 l_id t.id%TYPE;
4 BEGIN
5 cursor_pck.stored_proc(3, l_cursor);
6 LOOP
7 FETCH l_cursor INTO l_id;
8 EXIT WHEN l_cursor%NOTFOUND;
9 dbms_output.put_line(l_id);
10 END LOOP;
11 END;
12 /
1
2
3
PL/SQL procedure successfully completed
This is not going to work the way it's written, because
out_list expects a cursor, not a cursor result.
The name out_result_type is already used for a type, so you can't redefine it to be a cursor in the same scope.
Oracle provides a pre-defined weak reference cursor: sys_refcursor. In usage it would look like:
CREATE OR REPLACE PACKAGE pkg_test
AS
PROCEDURE prc_cur (p_retval OUT sys_refcursor,
p_lookup IN VARCHAR2);
END pkg_test;
CREATE OR REPLACE PACKAGE BODY pkg_test
AS
PROCEDURE prc_cur(p_retval OUT sys_refcursor
p_lookup IN VARCHAR2)
IS
BEGIN
OPEN retval FOR SELECT a.value
FROM tblname a
WHERE a.id <= p_lookup;
END prc_cur;
END pkg_test;
This saves you the trouble of needing to declare a type. The sys_refcursor is a pointer to a result set from an open cursor. If you are familiar with Java, it's the same concept as the java.sql.ResultSet object which provides a way to get at the results of a query.