Perfomance Out parameter vs Out system ref cursor Oracle Procedure - oracle

I have a Procedure in oracle with 12 parameters 4 of them are sys ref cursor. I am replace one cursor from my procedure using 8 more out parameters. Will there be any performance enhancement if use out parameters instead of out ref cursor.

A cursor can be thought of as a pointer to an area of memory within the database that contains a result set - it does not directly contain the results; so when you send a cursor you are just sending the pointer and then whatever user interface you are using will have to make additional round-trips to the database to use that cursor (pointer) to open the result set, fetch rows and then, when you are finished, close the cursor.
When you use an out parameter with individual values then the values can all be returned as the procedure terminates and no additional communication with the database is required.
Will there be any performance enhancement if use out parameters instead of out ref cursor.
So, yes, there may be a performance enhancement if you are returning multiple out parameters rather than a cursor which refers to a result set with a single row. However, as with all performance enhancements, you should profile the changes so that you can see the actual effect (which may be negligible).

Related

Creating Oracle Cursor using Java Program

I wanted to create Oracle Cursor with the help of Java Code. I tried searching on the Internet but I didn't find anything. Can we create Cursor using Java code?
You cannot create a cursor using Java code.
A cursor is a reference (pointer) to a data structure internal to the database representing a query and a corresponding set of results - creating the pointer outside of the database would be meaningless.
From the Oracle Documentation:
Introduction to REF CURSORs
Using REF CURSORs is one of the most powerful, flexible, and scalable ways to return query results from an Oracle Database to a client application.
REF CURSOR is a PL/SQL data type whose value is the memory address of a query work area on the database. In essence, a REF CURSOR is a pointer or a handle to a result set on the database. REF CURSORs are represented through the OracleRefCursor ODP.NET class.
REF CURSORs have the following characteristics:
A REF CURSOR refers to a memory address on the database. Therefore, the client must be connected to the database during the lifetime of the REF CURSOR in order to access it.
A REF CURSOR involves an additional database round-trip. While the REF CURSOR is returned to the client, the actual data is not returned until the client opens the REF CURSOR and requests the data. Note that data is not be retrieved until the user attempts to read it.
A REF CURSOR is not updatable. The result set represented by the REF CURSOR is read-only. You cannot update the database by using a REF CURSOR.
A REF CURSOR is not backward scrollable. The data represented by the REF CURSOR is accessed in a forward-only, serial manner. You cannot position a record pointer inside the REF CURSOR to point to random records in the result set.
A REF CURSOR is a PL/SQL data type. You create and return a REF CURSOR inside a PL/SQL code block.
You need to create a stored procedure (or function) in the database that returns a cursor and then invoke that from your external application.

Oracle: Using Procedure or Cursor to store a Select-Statement?

I have a PL/SQL package where i want to declare a select-statment which are used by different other Packages. So i see to ways. First way i define a cursor which can be called from other packages and store the select. Second way would be a procedure which stored the select.
Can someone tell me the advantages and disadvantages of each way? My Prof. say Cursor are old and statefull and noone use this today. My Chef tell me Cursor is faster to iterate and you can make Types of it.
Can someone tell me what's the best practice here?
For example:
CURSOR crs_active_customer IS
SELECT * FROM customer where status = 'active'
OR
PROCEDURE prc_getActiveCustomer IS
BEGIN
SELECT * FROM customer where status = 'active';
END prc_getActiveCustomer;
What is better way to store select-statements.
I would write a function that returns a new cursor instance every time you call it. A cursor variable in a package is actually a GLOBAL variable: you can have only one procedure at a time using it. This is probably the problem your professor is referring to.
Having a global cursor means that you will run into "cursor already open" errors if you write a a procedure that, while scanning the results of such cursor calls another function that internally needs to use the same cursor.
PL/SQL 101 to the rescue ! From Working with Cursors:
The central purpose of the Oracle PL/SQL language is to make it as easy and efficient as possible to query and change the contents of tables in a database. You must, of course, use the SQL language to access tables, and each time you do so, you use a cursor to get the job done.
So every time you have SQL in PL/SQL there will be a cursor. The next question is what kinds of cursors there is and when to use them. The above mentioned article touches also this topic.
You can also read the fine manual: Cursors
A cursor is a pointer to a private SQL area that stores information about processing a specific SELECT or DML statement.
And then carry on reading about implicit and explicit cursors.
Next find a better professor.

Return data rows from a pl/sql block

I want to write pl/sql code which utilizes a Cursor and Bulk Collect to retrieve my data. My database has rows in the order of millions, and sometimes I have to query it to fetch nearly all records on client's request. I do the querying and subsequent processing in batches, so as to not congest the server and show incremental progress to the client. I have seen that digging down for later batches takes considerably more time, which is why I am trying to do it by way of cursor.
Here is what should be simple pl/sql around my main sql query:
declare
cursor device_row_cur
is
select /my_query_details/;
type l_device_rows is table of device_row_cur%rowtype;
out_entries l_device_rows := l_device_rows();
begin
open device_row_cur;
fetch device_row_cur
bulk collect into out_entries
limit 100;
close device_row_cur;
end;
I am doing batches of 100, and fetching them into out_entries. The problem is that this block compiles and executes just fine, but doesn't return the data rows it fetched. I would like it to return those rows just the way a select would. How can this be achieved? Any ideas?
An anonymous block can't return anything. You can assign values to a bind variable, including a collection type or ref cursor, inside the block. But the collection would have to be defined, as well as declared, outside the block. That is, it would have to be a type you can use in plain SQL, not something defined in PL/SQL. At the moment you're using a PL/SQL type that is defined within the block, and a variable that is declared within the block too - so it's out of scope to the client, and wouldn't be a valid type outside it either. (It also doesn't need to be initialised, but that's a minor issue).
Dpending on how it will really be consumed, one option is to use a ref cursor, and you can declare and display that through SQL*Plus or SQL Developer with the variable and print commands. For example:
variable rc sys_refcursor
begin
open :rc for ( select ... /* your cursor statement */ );
end;
/
print rc
You can do something similar from a client application, e.g. have a function returning a ref cursor or a procedure with an out parameter that is a ref cursor, and bind that from the application. Then iterate over the ref cursor as a result set. But the details depend on the language your application is using.
Another option is to have a pipelined function that returns a table type - again defined at SQL level (with create type) not in PL/SQL - which might consume fewer resources than a collection that's returned in one go.
But I'd have to question why you're doing this. You said "digging down for later batches takes considerably more time", which sounds like you're using a paging mechanism in your query, generating a row number and then picking out a range of 100 within that. If your client/application wants to get all the rows then it would be simpler to have a single query execution but fetch the result set in batches.
Unfortunately without any information about the application this is just speculation...
I studied this excellent paper on optimizing pagination:
http://www.inf.unideb.hu/~gabora/pagination/article/Gabor_Andras_pagination_article.pdf
I used technique 6 mainly. It describes how to limit query to fetch page x and onward. For added improvement, you can limit it further to fetch page x alone. If used right, it can bring a performance improvement by a factor of 1000.
Instead of returning custom table rows (which is very hard, if not impossible to interface with Java), I eneded up opening a sys_refcursor in my pl/sql which can be interfaced such as:
OracleCallableStatement stmt = (OracleCallableStatement) connection.prepareCall(sql);
stmt.registerOutParameter(someIndex, OracleTypes.CURSOR);
stmt.execute();
resultSet = stmt.getCursor(idx);

Executing an Oracle stored procedure returning a REF CURSOR using SqlAlchemy

I have a stored procedure that I have defined in Oracle. In that procedure I need to return a recordset. To do this, I am using the SYS_REFCURSOR, which works great inside of Oracle (and with cx_Oracle, for that matter). In my application I am using SqlAlchemy scoped sessions, to support multi-threading.
How can I use the scoped session to return the REF CURSOR? The only way I have been able to get this to work is by declaring an out cursor with the cursor that is active in the session and then executing the stored procedure, like below:
sql = """
BEGIN
example('%s', '%s', '%s', :cur);
END;
""" % (cid, show, type)
conn = sa_tool.session.connection()
in_cur = conn._Connection__connection.cursor()
out_cur = conn._Connection__connection.cursor()
in_cur.execute(sql, cur=out_cur)
results = out_cur.fetchall()
Ideally, I would like to avoid using the connection object in this way, and execute the procedure while letting SqlAlchemy manage the cursors. If that is not possible, is there a reason that the fetch would take so long?
Thanks
I saw this question which was not answered and I decided to jump in. First of all, let me just say that for your scenario there is no better option than SYS_REFCURSOR. Of course, you have alternatives.
An Oracle Cursor is a memory area location where an instruction to execute a SQL statement is stored. A Ref cursor is just a pointer to the cursor location. SYS_REFCURSOR is an specific oracle defined typed of ref cursor. So when you return a SYS_REFCURSOR variable to a client, you are returning a pointer towards the memory location where the instruction to execute the SQL resides. Your client can now execute the instruction using the FETCH operation and get the rows. So this is the best possible way to return a result set to the client.
As an alternative, you might use a PIPELINED FUNCTION, but I can assure you that you won't get any better performance. AskTom has a great explanation about this comparison in this article
https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:9532870400346178516
Another scenario is whether you want to analyse where the time is consumed, either in the EXECUTE phase or in the FETCH one. If you have a huge time in FETCH, perhaps you might consider transfer the data in another way to the client. If you have a problem in EXECUTION, then you need to make a tuning exercise over your procedure.

trigger in oracle stored procedure

I have a requirement like this: I have to select a certain number of records from an Oracle table using a stored procedure. I will capture the entire resultset in ref cursors, but at the same time I have to update a flag in the selected records ( the ones stored in ref cursors).
So I want to know whether this is possible in stored procedure. If yes, then what do I have to use e.g. triggers?
Thanks in advance
A cursor doesn't "capture" or "store" anything. To store something, use a PL/SQL table.
Probably the closest thing to what you want to do:
DECLARE
type t_foobar is table of foobar;
v_foobar t_foobar;
BEGIN
UPDATE foobar SET flag=1 WHERE foo=bar AND flag=0 AND rowum<=10;
SELECT * FROM foobar BULK SELECT INTO v_foobar WHERE flag=1;
UPDATE foobar SET flag=2 WHERE flag=1;
COMMIT;
/* process v_foobar here */
END;
I'm doing two UPDATEs here so that in a concurrent environment, every session selects und updates different rows. (E.g. for a airplane seat reservation system)
It sounds like you are trying to ensure multiple processes do not select the same rows?
SELECT FOR UPDATE NO WAIT might be your best option.
http://download.oracle.com/docs/cd/E11882_01/appdev.112/e10472/static.htm#CIHHIIID
While that's 11.2 it will work for earlier versions of Oracle, like 10g.
Firstly you will not "capture the entire resultset in ref cursors", a ref cursor is a pointer to a result set. In effect, what you are returning is a query that will (or technically MAY) by executed by whatever receives it.
I'd forget the ref cursor and go with a pipelined table function. That way the procedure can process the records (ie flag them as updated) as it returns them to the caller.
Ref cursors are non-modifiable, as they exist only in memory. They are a reference, as indicated by the name. You will have to perform updates separately.

Resources