I want to See the text of the cursor. (the cursor has arguments and its take time to replace the arguments by their value myself) Thus I m trying to use the table v$open_cursor
In the IDE PLSQL developer, I debug a function which calls a cursor.
if not cursorName%isopen then
--A
open cBMIS (i_lanId, i_objectName, i_osUser, i_eventType, i_dateFrom, i_dateTo, i_interval);
--B
end if;
IN A and B I click on execute SQL in debug session in oder to execute this query :
select
sql_text
from
v$open_cursor
order
by last_sql_active_time desc
fetch
first 10 rows only
In A the cursor hasn’t appear in the result of the query yet. In B it should have appear, but it doesn’t. Why?
Related
I want to make a procedure in an anonymous block, which will display information about all database sessions that have unclosed transactions from the data dictionary views
BEGIN
select s.sid, s.serial#, s.username from v$transaction t inner join
v$session s on t.addr = s.taddr;
END;
But when I try to call it, nothing happens.
You have to follow your anonymous block with a '/', to tell oracle to stop parsing and start executing.
That said, your code still will just throw an error because you need to SELECT .... INTO some variable to hold the results of your SELECT.
And that said, even if you provide the correct variables and INTO syntax, your code still will not do what you expect, because PL/SQL is a server-side process that has no ability to display output. The closest it can come is to use DBMS_OUTPUT.PUT_LINE, but that just writes to a buffer that is returned, upon completion of the entire procedure, to the client. It is then up to the client to decide what do do with it.
And all that said, why do you think you need an anonymous PL/SQL block just to execute a simple query?
And all that said, screen shots of terminal sessions are very hard to read. It's actually very easy to simply copy the text from the terminal, and paste that into your postings. Then select the pasted text and click the 'code sample' icon of the edit window menu to set it off as formatted code.
If you really need an anonymous block, you can use the following code:
begin
for r_rows in (
select s.sid, s.serial#, s.username
from v$transaction t
inner join v$session s on t.addr = s.taddr) loop
dbms_output.put_line(r_rows.sid);
end loop;
end;
/
You must write the other columns in the dbms_output.put_line statement.
I'm experimenting with queries in an Oracle database (Using Oracle SQl Developer and PL/SQL Developer)
If I run a simple query: (SELECT * FROM myTable WHERE id = 1234) the results display in a nice grid in a lower pane of the SQL tool.
Now, how do I rewrite that query, using a variable for the 1234, And STILL have the results spill out into the results pane. Everything I've tried either won't compile, or requires me to do a SELECT...INTO and then manually output the results.
I just want to do something along the lines of this, and have it work:
DECLARE p0 = 1234;
SELECT * FROM myTable WHERE id = p0;
UPDATE:
In the actual query I'm working on, the variables will be more like:
DECLARE p0 = to_date('1/15/2014 7:11:05 AM','MM/DD/YYYY HH:MI:SS PM');
p1 = p0 + .0007; -- one minute later.
So being able to write that in code is important.
In Toad (or sqlplus or SQL Developer) you would do:
define x='20140820';
select to_date(&x, 'YYYYMMDD') from dual;
And run as a Script (important).
In Toad, the Output grid would be:
old: select to_date(&x, 'YYYYMMDD') from dual
new: select to_date(20140820, 'YYYYMMDD') from dual
TO_DATE(20140820,'YYYYMMDD')
----------------------------
20-AUG-2014
1 row selected.
And Grid1 would just show the results in table grid format.
Note that you can suppress the old/new in output by doing:
set verify off
at top of script.
One thing you can try is to create a bind variable named cur, for example, of type REFCURSOR, use OPEN :cur FOR SELECT ... in your PL/SQL block and then PRINT the cursor out. Here's an example with a very simple query:
VARIABLE cur REFCURSOR
BEGIN
OPEN :cur FOR SELECT * FROM DUAL;
END;
/
PRINT cur
This works in SQL*Plus and SQL Developer, although in the latter it will only work if you use the 'Run Script (F5)' button, not the 'Run Statement (Ctrl+Enter)' button. Also, you don't get a table with the results in, just the query output in preformatted text. Also, it won't necessarily work in other tools, as VARIABLE and PRINT are not part of SQL nor PL/SQL - SQL*Plus and SQL Developer both understand them and can interpret them.
In PL/SQL Developer you can use a Test Window for this kind of thing. For example, enter into a Test Window a PL/SQL block such as
BEGIN
OPEN :cur FOR SELECT * FROM DUAL;
END;
Then, either add the variable cur of type 'Cursor' to the variables table at bottom of the window, (or choose Scan Variables from the context menu. Note that PL/SQL Developer won't necessarily get the type right; you may well still have to change the type. Once you run the block, the results from the cursor can be obtained in a separate window by clicking the '...' button in the row in the variables table for cur.
As a minor variation on Luke's excellent answer, you don't even need a ref cursor if you just want to display a variable's value. Put this in a Test window:
declare
p0 date := to_date('1/15/2014 7:11:05 AM', 'MM/DD/YYYY HH:MI:SS PM');
begin
:p1 := p0 + .0007;
end;
then set up the p1 bind variable in the lower panel. Executing it will display the value.
I am learning Oracle.
CURSOR A FOR TABLE1
LOOP
DELETE B TABLE RECORD BASED ON CURSOR A
END LOOP
I am reading a Cursor from Table A, and based on the result i am deleting 2 more table entries. Please let me know in this case i need to provide FOR UPDATE OF while declaring Oracle or Its not needed. In DB2 i know we need to give with hold option.
How to get the current user details in the query in oracle. In sql server if we give USER then the details will come.
This link may be useful while learning Oracle: http://www.oracle.com/pls/db112/portal.all_books
Open this link, click on PL/ at the top of the page, then open PL/SQL Language Reference,
and in chapter 13 PL/SQL Language elements find DELETE Statement extension:
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/delete_statement.htm#LNPLS1187
Basically, to delete a record fetched from a cursor, a cursor must use FOR UPDATE clause, and a delete command must have WHERE CUFFENT OF <cursor-variable> clause.An example:
CURSOR c1 IS
SELECT employee_id, job_id, salary
FROM employees FOR UPDATE;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO my_emp_id, my_job_id, my_sal;
EXIT WHEN c1%NOTFOUND;
IF my_job_id = 'SA_REP' THEN
DELETE employees
WHERE CURRENT OF c1;
END IF;
END LOOP;
END;
In our application, we call various stored procedures that return reference cursors in the following fashion:
SELECT foo_package.sp_Bar('arg1', 'arg2', 'arg3', 'arg4') FROM dual;
What the wrap_xml function does is to convert the cursor result to an XML type, which will then be used in the application. After the conversion, it immediately closes the cursor (this step has solved memory issues for us before).
FUNCTION wrap_xml (c_result SYS_REFCURSOR)
RETURN XMLTYPE
IS
xml_val XMLTYPE;
BEGIN
xml_val := xmltype.CreateXML (c_result);
IF c_result%ISOPEN
THEN
CLOSE c_result;
END IF;
RETURN xml_val;
END;
In most cases, this appears to work fine: the XML is created and the cursors are closed. However, since introducing a stored procedure that opens a cursor for a dynamic query, we are observing a rapid increase in open cursors, eventually leading to:
ORA-01000: maximum open cursors exceeded
The dynamic query is built in order to "simulate" the results returned from other cursors, for testing purposes. For example, the stored procedure would build a dynamic query like this:
SELECT '1' as "COLUMN1", '990' as "COLUMN2", 'N' as "COLUMN3", NULL as "COLUMN5" FROM dual;
It would then open a cursor for this query string, and return the cursor:
OPEN rc_return FOR v_sql_query;
RETURN rc_return;
The resulting reference cursor is again passed to the wrap_xml function above, which I would expect to close the cursor – just like it does any other cursor. However, this doesn't seem to be the case, as the number of open cursors just keeps on growing. What could be the reason for this?
Additional investigation:
Stepping through the wrap_xml function, I can see the program flow skipping over the body of the c_result%ISOPEN check, implying that the cursor has indeed been closed. Yet it appears that the open cursor count still increases!
We appear to have plugged the leak by removing the ISOPEN check from the wrap_xml function and just executing the close cursor command in all cases. Apparently the ISOPEN flag is not set on cursors opened for dynamic SQL queries.
I am, however, unable to find a reference for this. Can anyone back this up?
I have a messy stored procedure which uses dynamic sql.
I can debug it in runtime by adding print #sql; where #sql; is the string containing the dynamic SQL, right before I call execute (#sql);.
Now, the multi-page stored procedure also creates dynamic tables and uses them in a query. I want to print those tables to the console right before I do an execute, so that I know exactly what the query is trying to do.
However, the SQL Server 08 does not like that. When I try:
print #temp_table; and try to compile the S.P. I get this error:
The name "#temp_table" is not permitted in this context. Valid expressions are constants, constant expressions, and (in some contexts) variables. Column names are not permitted.
Please help.
EDIT:
I am a noob when it comes to SQL. However, the following statement: select * from #tbl; does not print anything to the console when it is run non-interactively; the print statement works though.
The following statement has incorrect syntax: print select * from #tbl;. Is there a way for me to redirect the output of select to a file, if stdout is not an option?
Thanks.
When we use dynamic SQl we start by having a debug input variable in the sp (make it the last one and give it a default value of 0 (to indicate not in debug mode that way it won't break existing code calling the proc).
Now when you run it in debug mode, you print instead of execute or you print and execute but you always rollback at the end. If you need to see the data at various stages, the best thing to do is the second. Then before you rollback you put the data you want to see into a a table varaiable (This is important it can't be a temp table). after the rollback, select from the table variable (which did not go out of scope with the rollback) and run your print tstatments to see the queries which were run.
Debugging this way the only way you'll get output is
select * from #temp_table;
Alternatively, look into the debugging features built into SQL Server Management Studio. For example, this web page may help you
SQL Server Performance . com
You can print Variables, but not tables. You can, however, SELECT from the #table.
Now, if the table is created, filled up and modified in a single statement that is executed, then you can view the state of the table as it was before being modified, but the data will have changed since.
of course, as soon as the dynamic sql finishes, the #table is no longer available so you're stuck!
To counter that, you can insert into a ##Table (note the double hash marks) in your dynamic SQL along with the #table and then query that ##table at the end of execution of the dynamic sql.
for as much as I hate cursors, give this a try:
SET NOCOUNT ON
CREATE TABLE #TempTable1
(ColumnInt int
,ColumnVarchar varchar(50)
,ColumnDatetime datetime
)
INSERT INTO #TempTable1 VALUES (1,'A',GETDATE())
INSERT INTO #TempTable1 VALUES (12345,'abcdefghijklmnop','1/1/2010')
INSERT INTO #TempTable1 VALUES (null,null,null)
INSERT INTO #TempTable1 VALUES (445454,null,getdate())
SET NOCOUNT OFF
DECLARE #F_ColumnInt int
,#F_ColumnVarchar varchar(50)
,#F_ColumnDatetime datetime
DECLARE CursorTempTable1 CURSOR FOR
SELECT
ColumnInt, ColumnVarchar, ColumnDatetime
FROM #TempTable1
ORDER BY ColumnInt
FOR READ ONLY
--populate and allocate resources to the cursor
OPEN CursorTempTable1
PRINT '#TempTable1 contents:'
PRINT ' '+REPLICATE('-',20)
+' '+REPLICATE('-',50)
+' '+REPLICATE('-',23)
--process each row
WHILE 1=1
BEGIN
FETCH NEXT FROM CursorTempTable1
INTO #F_ColumnInt, #F_ColumnVarchar, #F_ColumnDatetime
--finished fetching all rows?
IF ##FETCH_STATUS <> 0
BEGIN --YES, all done fetching
--exith the loop
BREAK
END --IF finished fetching
PRINT ' '+RIGHT( REPLICATE(' ',20) + COALESCE(CONVERT(varchar(20),#F_ColumnInt),'null') ,20)
+' '+LEFT( COALESCE(#F_ColumnVarchar,'null') + REPLICATE(' ',50) ,50)
+' '+LEFT( COALESCE(CONVERT(char(23),#F_ColumnDatetime,121),'null') + REPLICATE(' ',23) ,23)
END --WHILE
--close and free the cursor's resources
CLOSE CursorTempTable1
DEALLOCATE CursorTempTable1
OUTPUT:
#TempTable1 contents:
-------------------- -------------------------------------------------- -----------------------
null null null
1 A 2010-03-18 13:28:24.260
12345 abcdefghijklmnop 2010-01-01 00:00:00.000
445454 null 2010-03-18 13:28:24.260
If I knew that your temp table had a PK, I'd give a cursor free loop example.