PL/SQL cursor-collection related query
Hi all,
I have a function which will take a collection (table of numbers) as a input argument.
Each id in the collection corresponds to a set of columns.I need to return a cursor which will contain the resultsets for all the ids in the collection.How do i do it.
what should the query be ?
say each id has three columns a,b,c to be returned.
I am given the collection of ids and am supposed to return a cursor which will have a,b,c columns for all the ids.
For individual ids , its straight forward
select a,b,c from sometable where id=input_id.
But how do i construct the cursor given a collection of ids?
Thanks in advance.
Hi,
Please see the below example:
SQL>CREATE TABLE T ( ID NUMBER(2),a NUMBER(2),b NUMBER(2),c NUMBER(2));
Table created.
SQL>SELECT * FROM t;
ID A B C
1 12 13 15
2 21 31 51
2 rows selected.
SQL>
Use the below query to create your cursor :
SQL>SELECT a,b,c FROM t tb1, TABLE( TBL_TYPE(1,2)) tb2 WHERE tb1.id = tb2.column_value;
A B C
12 13 15
21 31 51
2 rows selected.
SQL>Regards
Similar Messages
-
XSU - Maximal number of cursor in a query -(Typelength exceeds max value)
Hi,
Is there a way to increase the maximal number of cursors in a OracleXMLQuery object in XSU?
I have an object splitted in more than 50 tables and I need more than 50 cursors in order to get the whole object as XML.
XSU is giving me an error each time I try to get more than 50 cursors in a query:
<ERROR>oracle.xml.sql.OracleXMLSQLException: Typlaenge groesser als Hoechstwert</ERROR>
(sorry it is german, it means something like Typelength exceeds the maximal value)
It would be great if someone knows, I tried everything.
Cheers,
DiegoHi,
Go to context related method of Search view
- redifine method DO_INIT_CONTEXT, before redifine copy the existing code.
- Add the same code to your redfined method and specify the no of max hits required.
- if this is a custom application you can find the code in Standard Search applications like Quotation/Sale Order etc
Sample code :
method DO_INIT_CONTEXT.
data:
lv_cnode type ref to cl_bsp_wd_context_node_asp,
lr_qs type ref to cl_crm_bol_dquery_service.
field-symbols: <qs_name> type crmt_ext_obj_name.
set flag for later intialization in DO_PREPARE_OUTPUT
me->set_init_qs( abap_true ).
check if QS already exist
lv_cnode = get_dquery_cnode( ).
lr_qs ?= lv_cnode->collection_wrapper->get_first( ).
if lr_qs is not bound.
add empty QS in order to allow application to prefill values
assign lv_cnode->('BASE_ENTITY_NAME') to <qs_name>.
lr_qs = cl_crm_bol_dquery_service=>get_instance( <qs_name> ).
lv_cnode->collection_wrapper->add( lr_qs ).
endif.
Initialize maximum hits parameter if not yet set
data: data_ref type ref to data.
field-symbols: <max_hits> type i.
data_ref = lr_qs->get_property( iv_attr_name = 'MAX_HITS' )."#EC NOTEXT
assign data_ref->* to <max_hits>.
if data_ref is not bound or <max_hits> = 0.
data: max_hits_default type i.
max_hits_default = 20000. "cl_crm_ui_parameter_util=>get_search_max_hits( ).
lr_qs->set_property( iv_attr_name = 'MAX_HITS'
iv_value = max_hits_default ). "#EC NOTEXT
endif.
Comment out this code as you might get error for this.
register for change of dquery service
set handler on_dquery_changed for lv_cnode->collection_wrapper.
set handler on_config_data_changed.
endmethod.
Thanks,
Aniket
Edited by: Aaniket Korde on Dec 14, 2009 11:54 PM -
Returning SQL cursor from Stored Procedure
Hi,
I have a query regarding returning sql cursor from stored procedure to java in oracle 11g.
I want to query some data ex: my query returns A, B, C. Also, now I want to query some other data ex: D, E, F. Now I want to return this data as an sql cursor as a single row . Example: A,B,C,D,E,F. Is it possible to return/create a cursor in stored procedure?
assume both query returns equal number of rows.. however both are not related to each other..RP wrote:
Hi,
I have a query regarding returning sql cursor from stored procedure to java in oracle 11g.
I want to query some data ex: my query returns A, B, C. Also, now I want to query some other data ex: D, E, F. Now I want to return this data as an sql cursor as a single row . Example: A,B,C,D,E,F. Is it possible to return/create a cursor in stored procedure?
assume both query returns equal number of rows.. however both are not related to each other..It sounds like what you need is a ref cursor.
First thing to remember though is that cursors do not hold any data (see: {thread:id=886365})
In it's simplest form you would be creating a procedure along these lines...
SQL> create or replace procedure get_data(p_sql in varchar2, p_rc out sys_refcursor) is
2 begin
3 open p_rc for p_sql;
4 end;
5 /
Procedure created.
SQL> var rc refcursor;
SQL> exec get_data('select empno, ename, deptno from emp', :rc);
PL/SQL procedure successfully completed.
SQL> print rc;
EMPNO ENAME DEPTNO
7369 SMITH 20
7499 ALLEN 30
7521 WARD 30
7566 JONES 20
7654 MARTIN 30
7698 BLAKE 30
7782 CLARK 10
7788 SCOTT 20
7839 KING 10
7844 TURNER 30
7876 ADAMS 20
7900 JAMES 30
7902 FORD 20
7934 MILLER 10
14 rows selected.
SQL> exec get_data('select deptno, dname from dept', :rc);
PL/SQL procedure successfully completed.
SQL> print rc
DEPTNO DNAME
10 ACCOUNTING
20 RESEARCH
30 SALES
40 OPERATIONS
50 IT SUPPORTWhich takes an SQL statement (as you said that both your queries were unrelated), and returns a ref cursor, and then your Java code would fetch the data using that cursor.
Now, as for getting your rows to columns and combining two queries that do that... something along these lines...
SQL> select * from x;
C
A
B
C
SQL> select * from y;
C
D
E
F
SQL> ed
Wrote file afiedt.buf
1 select x.col1, x.col2, x.col3
2 ,y.col1 as col4
3 ,y.col2 as col5
4 ,y.col3 as col6
5 from (
6 select max(decode(rn,1,col1)) as col1
7 ,max(decode(rn,2,col1)) as col2
8 ,max(decode(rn,3,col1)) as col3
9 from (select col1, rownum rn from (select * from x order by col1))
10 ) x
11 cross join
12 (
13 select max(decode(rn,1,col1)) as col1
14 ,max(decode(rn,2,col1)) as col2
15 ,max(decode(rn,3,col1)) as col3
16 from (select col1, rownum rn from (select * from y order by col1))
17* ) y
SQL> /
C C C C C C
A B C D E F... will do what you ask. For further information about turning rows to columns read the FAQ: {message:id=9360005} -
Sending email using PL/SQL based on a query result
Hello all,
I want to create a procedure using PL/SQL, based on a query result.Here is the scenario:
I have multiple tables in Target and Source databases that I want to compare(not the whole table but queries on these tables) and if they differ, I want to shoot an email. I have some ideas how to implement this but not sure whether it is the best approach.
select Acct_id, total from SourceTableA
minus
select Acct_id, total from TargetTableA
select Acct_id, sum from SourceTableB
minus
select Acct_id, sum from TargetTableB
If the result of any of above queries > 0 then I want to shoot an email and want to repeat this procedure in the morning every day.
I know how to implement send_mail procedure using UTL_SMTP package and how to schedule tha job by dbms_job package. But I am not sure how to implement the result of minus query. In case if minus > 0 then I also want to send the name of tables in the email message where source and target tables are not same. Should i use cursor, variable or insert the result in a new table? any help would be highly appreciated. Thanks in advance.
KhanActually these queries are the part of our daily testing that we run everyday manually(after the scheduled ETL load) to see if there are any discrepencies between our datawarehouse tables and source tables. So instead of running these queries manually everyday we want to schedula a procedure that will shoot an email in case of any discrepency and indicate which tables have problems.
-
Need help on Dynamic SQL Cursor in Forms
Hi All,
I am trying to execute Dynamic SQL Cursor in forms using EXEC_SQL built in.
I have a cursor for example:
'select * from supplier where supplier = '||p_supplier||' and processing_order = '||p_order
My code is
cur_num := Exec_SQL.Open_cursor;
sql_order := 'select * from supplier where supplier = '||p_supplier||' and processing_order = '||p_order;
EXEC_SQL.PARSE(cursor_number, sql_order);
EXEC_SQL.DEFINE_COLUMN(cur_num ,1,ln_Supp_Id);
EXEC_SQL.DEFINE_COLUMN(cur_num ,2,ls_Suppl_Name,30);
EXEC_SQL.DEFINE_COLUMN(cur_num ,24,ls_exchange,20);
sql_count := EXEC_SQL.EXECUTE(cur_num );
While EXEC_SQL.FETCH_ROWS(cur_num ) > 0 Loop
EXEC_SQL.COLUMN_VALUE(cur_num ,1,ln_Supp_Id);
EXEC_SQL.COLUMN_VALUE(cur_num ,2,ls_Suppl_Name);
EXEC_SQL.COLUMN_VALUE(cur_num ,24,ls_exchange);
End Loop;
EXEC_SQL.CLOSE_CURSOR(cur_num );
In this case I have to write 24 Define Columns and 24 Column value. Is there any way to assign them to %rowtype at one time as I need all coulmn of the table.
I had similar case on multiple tables.
Please help me
Thanks,
MaddyI need this dynamic sql because p_supplier and p_order values changes at run time
I do not understand. Is this a simplified sample or the real thing? You do know that you can pass variables to cursors:
cursor test is
select * from supplier where supplier = p_supplier and processing_order = p_order;
or does e.g. p_supplier hold other parts of the query?
cheers -
SQL Query ( PL/SQL function body returning query ) page
Hello Friends,
I have a page with type SQL Query ( PL/SQL function body returning query ).
I have written a pl/sql block that returns a sql query - select statment.
Some times i am getting no data found error - does it got to do with the variable that stores the query .
=======================
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
Error ERR-1101 Unable to process function body returning query.
OK
=====================
When the query is returned with records where exactly the records are stored is it in the variable declared in pl/sql block or with the Oracle Apex implicit cursor.
Here's the pl/sql block ..
The query is generated while the user is navigating through pages ..
====================
declare
l_return_stmt varchar2(32767);
l_select varchar2(32000);
l_from varchar2(32000);
l_where varchar2(32000);
l_order_by varchar2(32000);
l_stmt_recordcount varchar2(32000);
l_recordcount number ;
begin
l_select := 'select '||:P10_VARLIST1||:P10_VARLIST2||:P10_VARLIST3
||:P10_VARLIST4||:P10_VARLIST5;
l_from := ' from '||:P10_RELATION;
if length(:P10_WHERE) > 0 then
l_where := ' where '||:P10_WHERE;
else
l_where := '';
end if;
if length(:P10_ORDER_BY) > 0 then
l_order_by := ' order by '||:P10_ORDER_BY;
else
l_order_by := '';
end if;
l_return_stmt := l_select||l_from||l_where||l_order_by;
:P10_STMT := l_return_stmt;
return l_return_stmt;
end;
=============================
Appreciate your help in this regard.
thanks/kumar
Edited by: kumar73 on Apr 22, 2010 6:38 AMIt looks like the query string you are trying to pass back exceeds the 32K limit for a varchar. Where this is happening is kind of difficult to tell as it could be any number of points, and also depends on what you are passing into the process via page items.
I would first try to establish what combination of page items causes this error to occur. Then, starting from the bottom and working your way backwards, I would start 'switching off' some of the items you use to build your query until it breaks again, thus establishing which part is leading to the error.
Also, I'm not sure what :P10_STMT is doing (are you maybe using this for visiblity of the query created)?
It looks like the query string you are trying to pass back exceeds the 32K limit for a varchar. Where this is happening is kind of difficult to tell as it could be any number of points, and also depends on what you are passing into the process via page items.
I would first try to establish what combination of page items causes this error to occur. then, starting from the bottom and working your way backwards, I would start 'switching off' some of the items you use to build your query until it breaks again, thus establishing which part is leading to the error.
Also, I'm not sure what :P10_STMT is doing (are you maybe using this for visiblity of the query created)? -
Size of PL\SQL Cursor block
I want to know the internal working of the PL\SQL Cursor. Lets start with a scenario.
1) I have 3 table with 20 million records each.
2) I am making a join out of them on a certain condition which gives me 60 million records, now I am putting them in a cursor.
Questions :
i) Can the Oracle PL\SQL Cursor is capable of holding that much records or there is any limit for it ?
ii) If there is a limit for such block, then where can I find it and how can I set it ?
3) If there is no such limit, then running such a query and holding all the data in the Cursor Block would degrade the performance. How Oracle handles such situations, It might be possible that Oracle only have the indexes of those records in the Cursor, but still it would be to time consuming to index 3 different table
Kindly Inform me about this issue ....
Thanks & regards
- Nabil Shams1. Oracle PL/SQL cursor is just a handle to shared SQL area in Oracle SGA and as such does not consume an awful lot of memory (I would dare to say it consumes peanuts). What is more important it does not depend on number of rows you are going to fetch via cursor
2. Therefore the answer to question 2 is NO
3. Running the query could and would affect you in most unpleasnat ways if you tried to store results of the query in your process memory (PGA/UGA), or more specifically if you created PL/SQL indexed by table and tried to pack all 60000000 rows into it.
If you fetch rows one by one, process the row, throw it away - then no problem... but what do you need to do it for? -
Need a column based off a PL/SQL cursor, how to do this?
Oracle9i Enterprise Edition Release 9.2.0.8.0 - 64bit Production
With the Real Application Testing option
JServer Release 9.2.0.8.0 - Production
Report Builder 10.1.2.2.0
ORACLE Server Release 10.1.0.5.0
Oracle Procedure Builder 10.1.2.2.0
Oracle ORACLE PL/SQL V10.1.0.5.0 - Production
Oracle CORE 10.1.0.5.0 Production
Hi,
I am trying to create a fairly basic report but in the initial data model query, I have one column that is built based off of a PL/SQL cursor. How do I add this into my report? I have tried to create a function under Program Units and reference the function in my select statement for the data model however it keeps saying it is an invalid identifier, and I assume its looking in our database and not the function I created inside the report.
This is what it looks like:
SELECT a.id,
b.name,
F_GET_GENERIC_NAME(b.code) "Generic Name",
c.strength...and the function i want it to use in my report:
FUNCTION F_GET_GENERIC_NAME (in_code varchar2) RETURN VARCHAR2 IS
BEGIN
DECLARE
generic_name table.column%TYPE;
CURSOR cs_get_generic_name IS
SELECT /*+ USE_HASH (AR) */ desc
FROM a_ref AR, ai_ic AC
WHERE AC.code = in_code
AND AC.code = AR.code
ORDER BY sort_nbr;
BEGIN
generic_name := '';
FOR v_get_generic_name IN cs_get_generic_name
LOOP
generic_name := generic_name || RTRIM(v_get_generic_name.desc)
|| '/' || ' ';
END LOOP;
generic_name := SUBSTR(generic_name, 1,(NVL(LENGTH(generic_name), 0) - 2));
RETURN generic_name;
END;
END;
Any suggestions? Should I just create the function in the database?I am trying to do it through a formula column but am encountering the following problem.
I've created a formula column in my data model where I want the column to be (inside the group).
Inside the PL/SQL for the column I reference the function that I had previously created with the following:
function CF_Generic_nameFormula return Char is
begin
F_GET_GENERIC_NAME(:code);
end;However it won't let me compile, giving the error that "F_GET_GENERIC_NAME is not a procedure or is undefined." Is there something else that I am missing?
EDIT: Nevermind, i missed something simple like putting a return in front of the function call.
Edited by: a small rabbit on Nov 3, 2009 10:43 AM
Edited by: a small rabbit on Nov 3, 2009 10:44 AM -
At what point is PL/SQL cursor data retrieved?
Hi
This may sound like a silly question but since I am not entirely sure, I thought I'd ask.
In Oracle PL/SQL, do you know at what stage the query in a cursor is actually executed?
Is it at the DECLARE stage or when you first OPEN / LOOP on it?
I suspect upon the OPEN or the LOOP.
I.e. if I had a cursor declared but did not loop (using FOR .. LOOP) through it for some hours, would the query results be as at the time of declare or as at the time of the OPEN / FOR...LOOP?
E.g.
CURSOR invoices
IS
SELECT invoice_number
FROM unpaid_invoices
WHERE due_date < TRUNC (SYSDATE)
BEGIN
-- Some time consuming processing that will take an hour
-- Start Loop through cursor of invoices.
<<overdue_invoices>>
FOR inv IN invoices LOOP
-- Some processing on the invoice
END LOOP overdue_invoices;
END;Would the cursor details for invoices be as at the CURSOR declaration or when the FOR inv... is reached?
Thanks
MartinWhen you use a for loop like that it implicitly opens the cursor at the start and closes it at the end of the loop.
But the SQL query in that cursor is actually "run" when the first implicit or explicit fetch is issued, and retrieves new rows for every subsequent fetch.
Of course, before rows can be retrieved there needs to be several other tasks.
There's a good description of the steps of SQL processing in this part of the documentation.
http://download.oracle.com/docs/cd/E11882_01/appdev.112/e10471/adfns_sqlproc.htm
PL/SQL implicitly declares a cursor for all SQL data manipulation statements, including queries that return only one row. For queries that return multiple rows, you can explicitly declare a cursor to process the rows individually.
A cursor is a handle to a specific private SQL area. In other words, a cursor can be thought of as a name for a specific private SQL area. A PL/SQL cursor variable enables the retrieval of multiple rows from a stored subprogram.Edited by: fsitja on Dec 15, 2009 1:03 AM -
I need somebody to help me with sql cursors, in JSP.
This is my peace of code what is wrong with it?
Statement stmt = myConn.createStatement();
stmt.executeQuery("BEGIN WORK");
stmt.executeQuery("DECLARE item_cursor CURSOR FOR SELECT user_name FROM admin_info");
stmt.executeQuery("FETCH 10 FROM item_cursor");
ResultSet rs = stmt.getResultSet();
while(rs.next()){
if(rs.getString(1) != null){
user_name = rs.getString(1).trim();
%><P><%= user_name %></P><%
stmt.executeQuery("CLOSE item_cursor");
stmt.executeQuery("COMMIT WORK");
and this is the error that a get: No results where returned by the query
Please help anybody
thanx guysIf you are using ORACLE drivers and classes.
This sample program shows Oracle JDBC REF CURSOR functionality, creating a PL/SQL package that includes a stored function that returns a REF CURSOR type. The sample retrieves the REF CURSOR into a result set object.
* This sample shows how to call a PL/SQL function that opens
* a cursor and get the cursor back as a Java ResultSet.
import java.sql.*;
import java.io.*;
import oracle.jdbc.driver.*;
class RefCursorExample
public static void main (String args [])
throws SQLException
// Load the driver
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
// Connect to the database
// You can put a database name after the @ sign in the connection URL.
Connection conn =
DriverManager.getConnection ("jdbc:oracle:oci8:@", "scott", "tiger");
// Create the stored procedure
init (conn);
// Prepare a PL/SQL call
CallableStatement call =
conn.prepareCall ("{ ? = call java_refcursor.job_listing (?)}");
// Find out all the SALES person
call.registerOutParameter (1, OracleTypes.CURSOR);
call.setString (2, "SALESMAN");
call.execute ();
ResultSet rset = (ResultSet)call.getObject (1);
// Dump the cursor
while (rset.next ())
System.out.println (rset.getString ("ENAME"));
// Close all the resources
rset.close();
call.close();
conn.close();
// Utility function to create the stored procedure
static void init (Connection conn)
throws SQLException
Statement stmt = conn.createStatement ();
stmt.execute ("create or replace package java_refcursor as " +
" type myrctype is ref cursor return EMP%ROWTYPE; " +
" function job_listing (j varchar2) return myrctype; " +
"end java_refcursor;");
stmt.execute ("create or replace package body java_refcursor as " +
" function job_listing (j varchar2) return myrctype is " +
" rc myrctype; " +
" begin " +
" open rc for select * from emp where job = j; " +
" return rc; " +
" end; " +
"end java_refcursor;");
stmt.close(); -
Understanding SQL cursor attributes
I was trying to understand the use of SQL cursor attributes.So i chose sql%notfound attribute to be used with an exception in the below example.
create or replace procedure checkExcp
is
v_empName varchar2(30);
exp_no_row_found exception;
errorMessage varchar2(500);
begin
select ename into v_empName from emp where empno = '8000';
if sql%notfound then
raise exp_no_row_found ;
end if;
exception
when exp_no_row_found
then
errorMessage := 'Error occured while executing updateInventoryTotalsInDB function: ';
end;When i debugged this proc i realized that the
if sql%notfound then
raise exp_no_row_found ;bit of the code(and the custom exception exp_no_row_found) is useless. Because when no rows are returned by the query
select ename into v_empName from emp where empno = '8000';it straightaway goes to the exception block bypassing the 'if sql%notfound....' bit. So when is a SQL cursor attribute like sql%notfound useful?But i want to add specific error messages to each
SELECT...INTO statements. So a single,common
NO_DATA_FOUND exception would mask these specific
errors.Then don't make it a single, common exception block. Have specific execution blocks with their own exception block for each different way you want to handle the exception e.g.
BEGIN
BEGIN
SELECT mydata INTO myvar FROM mytable;
EXCEPTION
WHEN NO_DATA_FOUND THEN
myvar := 'No data for myvar';
END;
BEGIN
SELECT myotherdata INTO myvar2 FROM mytable;
EXCEPTION
WHEN NO_DATA_FOUND THEN
myvar2 := 'No data for myvar2';
END;
END;Nested execution blocks are your friend when you want to handle exceptions for specific areas. -
Building report from PL/SQL cursor
Hello,
is there any way to build APEX report using just PL/SQL cursor?
I don't have grant to SELECT from views or tables, but I can use some functions returning row types and cursors. I know I can use them to build table from scratch with htp.p etc., but it’s not very nice. I want to do it using APEX reporting with filtering and pagination functionality.
Is it possible?
Regards,
PrzemekApologies for the delay, I was out of the office.
Below is a package serving as the basis for creating a view based on a pipelined function. The package is just a skeleton and will not compile in its current form, you will need to go through it filling in the blanks as described by the comments.
If you want some control over what rows are returned by the view from a larger result set, use the set_parameters function in the WHERE clause, E.G.:
select * from really_big_complicated_slow_view where 1 = view_pkg.set_parameters(something_that_reduces_the_view_result_set_size);
Or, a more concrete example:
select result_text from view_to_convert_to_csv where 1 = view_pkg.set_parameters(pi_table => 'my_table', pi_where = 'whatever');
In the spirit of full disclosure, I got the idea for using the "set_parameters" function in the view WHERE clause from a post or blog somewhere a couple of years ago but have lost track of who actually deserves the credit for the good idea.
-Tom
create or replace package demo_vw as
-- Package to serve as the basis for a view based on a function
-- Customize this record so that it represents a row from this view...
type row_type is record (
-- record fields here
type table_type is table of row_type;
-- This function is used in the DDL to define the view, for example:
-- create or replace view my_view (col1, col2, ..., colN) as
-- select * from table(my_view_vw.get_view);
function get_view
return table_type
pipelined;
-- Customize this function header to accept the parameters for this view, if
-- any. If this view does not require any parameters, the set_parameters
-- function may be deleted.
-- This function should always return 1 and is called as follows
-- select <whatever>
-- from my_view
-- where 1 = my_view_vw.set_parameters(p1, p2, p3, ..., pN);
function set_parameters (pi_whatever1 in whatever,
pi_whateverN in whatever)
return number;
end demo_vw;
show error package demo_vw
create or replace package body demo_vw as
-- Customize this list of private global variables to match the parameters
-- required by the view. These variables are set, reset, and validated by
-- set_parameters, reset_parameters, and valid_parameters respectively...
g_var1 whatever;
g_varN whatever;
function set_parameters (pi_whatever1 in whatever,
pi_whateverN in whatever)
return number
is
-- Customize this function header to accept the parameters for this view, if
-- any. If this view does not require any parameters, the set_parameters
-- function may be deleted.
-- This function should always return 1 and is called as follows
-- select col1, col2, ..., colN
-- from my_view
-- where 1 = my_view_vw.set_parameters(p1, p2, p3, ..., pN);
begin
g_var1 := pi_whatever1;
g_varN := pi_whateverN;
return 1;
end set_parameters;
function valid_parameters
return boolean
is
-- Customize...
-- Assumes that set_parameters has been called to set the value of the view
-- parameters.
l_valid boolean := true;
begin
return l_valid;
end valid_parameters;
procedure reset_parameters
is
-- Customize...
-- This is called at the end of the get_view function to reset the view
-- parameters for the next caller.
begin
g_var1 := null;
g_varN := null;
end reset_parameters;
function get_view
return table_type
pipelined
is
-- build and return each row for the view...
l_row row_type;
begin
if valid_parameters then
-- do your process to populate the l_row variable here...
pipe row (l_row);
end if;
reset_parameters;
exception
when others then
reset_parameters;
raise;
end get_view;
end demo_vw;
show error package body demo_vw
create or replace view demo
as
select * from table(demo_vw.get_view); -
Hello,
since migrating our system from Oracle Client 9.0.X to 9.2.0.1 (Windows XP), i am encountering troubles when calling a stored procedure from a Cobol-Program:
after a while i run into a 'Maximum open cursors exceeded'-message (ORA-01000)
The stored procedure returns a cursor (ref_cursor)
When Executing the stored procedure, there are actually 2 cursors involved, in fact the stored PL/SQL procedure implicitely opens a child-cursor when doing a select within the PL/SQL.
After fetching the result and closing the cursor in my cobol-program, it correctly closes the cursor associated with the stored-procedure, but it does not close the cursor that was implicitely opened by oracle.
After a while i am running into a Maximum open cursors message, because those cursors have not properly been closed.
Here's a simple PL/SQL package that illustrates the problem:
create or replace package scott.SCOTTS_PACKAGE is
type ref_cursor IS REF CURSOR;
function GET_EMP(EMP_IN CHAR) return ref_cursor;
end SCOTTS_PACKAGE;
create or replace package body scott.SCOTTS_PACKAGE is
-- Function and procedure implementations
function GET_EMP(EMP_IN CHAR) return ref_cursor is
MyCurs ref_cursor;
begin
OPEN MyCurs FOR
SELECT EMPNO ,
ENAME ,
JOB
FROM SCOTT.EMP
WHERE ENAME = EMP_IN;
return(MyCurs);
end;
end SCOTTS_PACKAGE;
Here are some exerpts from my cobol program:
(The program iterates 100x through the section that executes the PL/SQL. After each iteration an additional open cursor remains in the database)
003800 EXEC SQL BEGIN DECLARE SECTION END-EXEC.
003900*
004000 01 SQL-USERNAME PIC X(16) VARYING.
004100 01 SQL-PASSWD PIC X(16) VARYING.
004200 01 SQL-DBNAME PIC X(64) VARYING.
004300 01 ORACLE.
004700 02 ORA-CUR-EMP SQL-CURSOR.
01 EMPREC.
02 EMPREC-EMPNO PIC X(4).
02 EMPREC-ENAME PIC X(10).
02 EMPREC-JOB PIC X(9).
005400 EXEC SQL END DECLARE SECTION END-EXEC.
018400 PROCEDURE DIVISION.
CONTINUE.
018700 EXEC SQL
018800 WHENEVER SQLERROR DO PERFORM SQL-ERROR
018900 END-EXEC.
019000*
CONTINUE.
019100 EXEC SQL
019200 WHENEVER NOT FOUND DO PERFORM SQL-NOT-FOUND
019300 END-EXEC.
022400 EXEC SQL
022500 ALLOCATE :ORA-CUR-EMP
022600 END-EXEC
PERFORM VARYING I FROM 1 BY 1 UNTIL I > 100
ACCEPT DUMMY FROM TER
IF DUMMY = "E"
MOVE 100 TO I
END-IF
PERFORM GET-EMP
ADD 1 TO I
END-PERFORM
119300 GET-EMP SECTION.
119400************************
119500 GAM0.
MOVE SPACES TO EMPREC-EMPNO EMPREC-JOB
MOVE "SMITH" TO EMPREC-ENAME
120200 EXEC SQL AT SSSI EXECUTE
120300 BEGIN
120400 :ORA-CUR-EMP:=
120500 SCOTT.SCOTTS_PACKAGE.GET_EMP(:EMPREC-ENAME );
120900
END;
121000 END-EXEC
121200 IF DB-ERR-CODE NOT = HIGH-VALUE
121300 DISPLAY "CCSIFSO:GET-AUTRE-MATR:APPEL PERS... OK"
121400 EXEC SQL
121500 FETCH :ORA-CUR-EMP
121600 INTO
121700 :EMPREC-EMPNO,
121800 :EMPREC-ENAME,
121900 :EMPREC-JOB
122400 END-EXEC
122500 END-IF
122600*
122700 IF DB-ERR-CODE NOT = HIGH-VALUE
122800 DISPLAY "CCSIFSO:GET-AUTRE-MATR:APPEL FETCH.. OK"
123000 ELSE
123100 MOVE LOW-VALUE TO DB-ERR-CODE
123200 END-IF
123300 EXEC SQL
123400 CLOSE :ORA-CUR-EMP
123500 END-EXEC
123600 GA-EX.
123700 EXIT.
124000 SQL-NOT-FOUND SECTION.
124100*----------------------
124200 NF0.
124300 DISPLAY "CCSIFSO:SQL-NOT-FOUND SECTION."
124400 MOVE HIGH-VALUE TO DB-ERR-CODE.
124500 NF-EX.
124600 EXIT.
124700*
124800 SQL-ERROR SECTION.
124900*-----------------
125000 ER0.
125200 EXEC SQL
125300 WHENEVER SQLERROR CONTINUE
125400 END-EXEC
125700 MOVE HIGH-VALUE TO DB-ERR-CODE
125800*
126100 DISPLAY "ORACLE ERROR DETECTED: " SQLCODE UPON TER
126200 DISPLAY SQLERRMC UPON TER
126300*
126400 EXEC SQL AT SSSI
126500 ROLLBACK WORK
126600 RELEASE
126700 END-EXEC
126800 DISPLAY "----------------------------" UPON TER
126900 DISPLAY " ! ROLLBACK ET DISCONNECT ! " UPON TER
127000 DISPLAY "----------------------------" UPON TER
127200 CALL "PPTERMJ".
127400 ER-EX.
127500 EXIT.
Finally here's an exerpt from V$OPEN_CURSOR, after a few iterations:
1 begin :b1 := SCOTT . SCOTTS_PACKAGE . GET_EMP (:b2 ) ; END ;
2 SELECT EMPNO , ENAME , JOB FROM EMP WHERE ENAME = :B1
3 SELECT EMPNO , ENAME , JOB FROM EMP WHERE ENAME = :B1
4 SELECT EMPNO , ENAME , JOB FROM EMP WHERE ENAME = :B1
5 SELECT EMPNO , ENAME , JOB FROM EMP WHERE ENAME = :B1
6 SELECT EMPNO , ENAME , JOB FROM EMP WHERE ENAME = :B1
7 SELECT EMPNO , ENAME , JOB FROM EMP WHERE ENAME = :B1
8 SELECT EMPNO , ENAME , JOB FROM EMP WHERE ENAME = :B1
9 SELECT EMPNO , ENAME , JOB FROM EMP WHERE ENAME = :B1
10 SELECT EMPNO , ENAME , JOB FROM EMP WHERE ENAME = :B1
11 SELECT EMPNO , ENAME , JOB FROM EMP WHERE ENAME = :B1
As you see, there is only 1 cursor starting with 'begin ... '
but there are 10 implicit cursors 'SELECT EMPNO, ... ' that have not been properly closed, nor reused by ORACLE.
In our old configuration (ORACLE CLient 9.0.X), you would only see:
1 begin :b1 := SCOTT . SCOTTS_PACKAGE . GET_EMP (:b2 ) ; END ;
2 SELECT EMPNO , ENAME , JOB FROM EMP WHERE ENAME = :B1
meaning all the other cursors have properly been closed.
As a conclusion: the program correctly closes the implicit cursors when using a 9.0 Client, wheras the implicit cursors remain open on Client 9.2.0.1 (Windows XP)
The underlying database can be either 8.i or 9, the problem remains the same.
Finally here's a small Delphi code, using ODAC-components, that somewhat illustrates the same problem:
procedure TForm1.ExecProcClick(Sender: TObject);
var I: INTEGER ;
begin
FOR I := 1 TO 5 DO
BEGIN
SP1.StoredProcName:='SCOTT.SCOTTS_PACKAGE.GET_EMP';
SP1.Prepare;
SP1.ParamByName('EMP_IN').AsString := 'SMITH';
SP1.ExecProc;
SP1.Next;
SP1.Close;
SP1.UnPrepare;
END;
end;
After each call to 'PREPARE', an additional implicit cursor remains open on the database. (using Oracle Client 9.2.0.1)
On our old system (Oracle Client 9.0 or 8.X), the same program would not generate accumulating open cursors on the database
Any suggestions would be welcome,
ClaudeCobol.. been many years since I last even saw some Cobol source code. Invokes all kinds of memories. :-)
Since you found the patch, the advice is superfluous, but works. Close the cursor at the PL/SQL side, e.g.
create or replace procedure CloseRefCursor( cRefCursor TYPELIB.TRefCursor ) is
begin
close cRefCursor;
exception when OTHERS then
-- if the cursor is already gone, not a problem
NULL;
end;In Delphi for example, one can subclass the class used for ref cursor calls and add a call to the above PL/SQL proc in the destructor. Or add create a standard Cobol close ref cursor section that does similar. -
Error while executing Procedure - ORA-06511: PL/SQL: cursor already open
I have successfully compiled the following procedure but when I execute it, following error occurs, please adv.
Thanks and Regards,
Luqman
create or replace
procedure TESTKIBOR
(contno in varchar)
AS
BEGIN
DECLARE cursor c1 is
SELECT * FROM KIBOR_SCHEDULE
WHERE CN=contno;
begin
OPEN C1;
FOR line IN c1 LOOP
update kibor_schedule
set lincome=line.Lincome,
expo=line.eXPO,
pport=line.pPORT
where cn=line.cn
and rno=line.rno;
END LOOP;
COMMIT;
close c1;
END;
END TESTKIBOR;
ERROR at line 1:
ORA-06511: PL/SQL: cursor already open
ORA-06512: at "MKTG.TESTKIBOR", line 6
ORA-06512: at "MKTG.TESTKIBOR", line 10
ORA-06512: at line 1Hi,
CREATE OR REPLACE PROCEDURE Testkibor
(contno IN VARCHAR)
AS
BEGIN
DECLARE
CURSOR c1 IS
SELECT *
FROM kibor_schedule
WHERE cn = contno;
BEGIN
--// OPEN c1; --no need to open if using for loop
FOR line IN c1 LOOP
UPDATE kibor_schedule
SET lincome = line.lincome,
expo = line.expo,
pport = line.pport
WHERE cn = line.cn
AND rno = line.rno;
END LOOP;
COMMIT;
--// CLOSE c1; -- no need for loop does it for you
END;
END testkibor;SS -
PL/SQL function in datamodel query
Hi All,
I have the following problem:
I have a query Q1 returning a few rows. In the group G1 using this query Q1 i have a computed field returning a number NUM_1.
select col_1, col_2 from table_1;
So the output looks like:
row 1 col_1 col_2 NUM_1_1
row n col_1n col_2n NUM_1_n
I want to order these rows by the calculated column NUM_1 the highest first.
I know i can't order by a calculated column but can i do it by using a pl/sql function in the query to calculate the NUM_1?
Like:
select col_1, col_2, function(x) NUM_1 from table_1;
And where should i create this function? Can it be done in the program unit section or do i have to create a library?
Best regards,
SnoeskyOke, i have created a break group on the calculated field.
Ordering works fine now.
I have an additional question:
Is it possible to dynamically order this break (column) group? Meaning thru a parameter to tell the ordering to be descending or ascending.
Regards,
Snoesky
Maybe you are looking for
-
I am having trouble with hdmi from MacBook to TV
Having trouble with the sounds when I connect hdmi from MacBook to TV
-
How to find the Size of a Folder &also list the sub folder and files in it
In my program I want to know the size of a folder . The input given is the path of the folder and the ouptut should be the list of files and subfolders with their size. What is the function we have to use for this? Thank you
-
Receiver determination doesn't work for same IDoc type but in differentSWCV
hi guys, we have an emergency now. Receiver determination doesn't work for same IDoc type but in different SWCV.Please check below for detail. 1. The process flow is : R/3 IDoc -> XI -> Third party system 2. In previous release R13, IDoc ORDERS05 was
-
Shutdown of the server and problems with some reports
Hello, A fatal shutdown of the ERP server arrived. Now we have some errors and dumps for some transactions. Dumps examples : A RAISE statement in the program "CL_GUI_ALV_TREE===============CP" raised the exception condition "DP_ERROR". Since the ex
-
Project in java using collabrative technique
can any one give the project in java using collabrative filetering technique. i mean to say ,i want a project in java which must use the technique given above. its very urgent please help in this aspect..