How to inspect a cursor variable in a debug session?
In a function inside the body of a package I do...
Example:
V_SITUACIONESACTYHIST C_SITUACIONESACTYHIST%ROWTYPE;
BEGIN
FOR v_SituacionesACTyHIST IN c_SituacionesACTyHIST( p_id_DECE400, p_idpers )
LOOP
IF ( V_SITUACIONESACTYHIST.ESTADO_SITUACION = 'S' ) THEN
v_hay_regs_hist:=1;
END IF;
END LOOP;
where the cursor variable c_SituacionesACTyHIST is declared in the specifications package (Is this the problem, because is a global declaration?).
When debugging I cannot inspect the value of V_SITUACIONESACTYHIST.ESTADO_SITUACION or whatever cursor variable field; I always obtain "NULL" as value...
Why?
How can I see the value of that variables?
I have the same problem in v2.1 and 1.5.5 version of sqldeveloper.
Thanks.
Edited by: pacoKAS on 11-feb-2010 0:14
Edited by: pacoKAS on 11-feb-2010 0:17
Edited by: pacoKAS on 11-feb-2010 0:17
Edited by: pacoKAS on 11-feb-2010 0:19
Edited by: pacoKAS on 11-feb-2010 0:21
Edited by: pacoKAS on 11-feb-2010 0:22
Edited by: pacoKAS on 11-feb-2010 0:22
I'm proposing that you don't have a variable named the same as your cursor variable.
CREATE OR REPLACE
PROCEDURE P1
AS
CURSOR test_cur
IS
SELECT owner, table_name FROM all_tables WHERE ROWNUM <= 10;
-- x test_cur%rowtype; /* This variable is not needed. */
BEGIN
FOR x IN test_cur /* If you don't have another variable named x somewhere, you can see values for x */
LOOP
dbms_output.put_line(x.owner || '.' || x.table_name);
END LOOP;
END P1;from your example...
V_SITUACIONESACTYHIST C_SITUACIONESACTYHIST%ROWTYPE;
BEGIN
FOR v_SituacionesACTyHIST IN c_SituacionesACTyHIST( p_id_DECE400, p_idpers )
LOOP
IF ( V_SITUACIONESACTYHIST.ESTADO_SITUACION = 'S' ) THEN
v_hay_regs_hist:=1;
END IF;
END LOOP;You're declaring your variable twice:
(1) V_SITUACIONESACTYHIST C_SITUACIONESACTYHIST%ROWTYPE;
(2) FOR v_SituacionesACTyHIST IN c_SituacionesACTyHIST
When you're debugging, it's looking at the first version...which is null because you haven't assigned anything to it. When you use a Cursor For-Loop like that, it implicitly declares the variable for you. You don't have to do it in your DECLARE section.
Edited by: DylanB123 on Feb 16, 2010 1:04 PM
Similar Messages
-
How to pass a litral string into cursor variable?
Hi All
I have a code like below:
I need to select the following table,column with the criteria as such but it looks like the literal string does not work for cursor variable.
I can run the SQL in sqlplus but how I can embed that in PL/SQL code??
-Thanks so much for the help
cursor ccol2(Y1 varchar2) is select table_name,column_name from user_tab_columns
where table_name like 'HPP2TT%' and table_name like '%Y1'
and column_name not in ('MEMBERID');Literal strings are fine in a cursor, however, your logic is likely wrong, and you are not using the Y1 parameter to the cursor correctly. If you are looking for tables that either start with HPP2TT or end with Y1 (whatever you pass as Y1), then you need something more like:
cursor ccol2(Y1 varchar2) is
select table_name, column_name
from user_tab_columns
where (table_name like 'HPP2TT%' or
table_name like '%'||Y1) and
column_name not in ('MEMBERID');In the unlikely event that you are lookig for table that actually do start with HPP2TT and end in whatever is passed in Y1 then your query could be simplified to:
cursor ccol2(Y1 varchar2) is
select table_name, column_name
from user_tab_columns
where table_name like 'HPP2TT%'||Y1 and
column_name not in ('MEMBERID');Note in both cases, a single member in-list is bad practice, although Oracle will transform it to an equality predicate instead.
John -
PL/SQL package hasc1 in out cursor variable param.how to exec @ SQL
I have a PL/SQL procedure with 1 in out parameter which is cursor variable. How to execute this procedure on SQL prompt?
My code looks like this:
CREATE OR REPLACE PACKAGE PackFlight AS
TYPE GenCurType is REF CURSOR;
PROCEDURE searchFlight(pdate in flight.flight_date%TYPE,
gen_cursor IN OUT GenCurType);
END PackFlight;
I want to execute this procedure at SQL Prompt? Could you please tell me how to do this?
If I create a stand-alone procedure with ref-cursor, then how to execute this @ SQL Prompt?
Thanks a lot,
Supriyavar rc refcursor
exec packflight.searchflight (sysdate, :rc); -
How to (in Pro*C) pass a cursor variable as a pointer between functions
I am opening a cursor in a called function that accepts as one argument a pointer to a cursor variable, and a second argument for the sql string defining the cursor select. That works fine, and in that same function can successfully fetch and access the records from the cursor. However, my objective is to fetch the records in another function that calls the first function. I want to pass back to the calling function the pointer to the cursor variable from the first function. In the second (calling) function, is where I want to fetch the records. What I am getting is SQLCODE = -1002 (fetch out of sequence).
Here is the relevent code in the first called function that calls a PL/SQL package procedure to open the cursor, followed by the code in the second calling procedure where I am attempting to fetch the records:
/******Called function code starts here ******/
EXEC SQL INCLUDE SQLCA;
long db_makeCursor(cursorID, SQLstr)
EXEC SQL BEGIN DECLARE SECTION;
sql_cursor cursorID; / a pointer to a cursor variable */
char *SQLstr;
EXEC SQL END DECLARE SECTION;
long SQLCODE;
EXEC SQL BEGIN DECLARE SECTION;
sql_cursor dbCursor; /* a cursor variable */
EXEC SQL END DECLARE SECTION;
EXEC SQL WHENEVER SQLERROR DO sql_error();
dbCursor = *cursorID;
EXEC SQL EXECUTE
BEGIN
db_util_ref_cursor_pkg.open_dbNameCursor( :dbCursor, :SQLstr );
END;
END-EXEC;
return;
/******Calling function code starts here ******/
EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
static PROCLOG PROC_Rec;
EXEC SQL END DECLARE SECTION;
long retrieveProcesses( _proclog, sqlForProcLog )
EXEC SQL BEGIN DECLARE SECTION;
PROCLOG _proclog;
char *sqlForProcLog
EXEC SQL END DECLARE SECTION;
long rc;
long SQLCODE;
EXEC SQL BEGIN DECLARE SECTION;
sql_cursor dbCursor; /* a cursor variable */
sql_cursor cursorID; / a pointer to a cursor variable */
PROCLOG proclog;
short end_ts_ind;
short proc_name_ind;
short comments_ind;
EXEC SQL END DECLARE SECTION;
cursorID = &dbCursorName; /* assign a value to the pointer */
EXEC SQL ALLOCATE :dbCursor;
rc = dbUtilities_makeCursor( cursorID, sqlForProcLog);
if (rc == TRUE)
while (SQLCODE == 0)
EXEC SQL FETCH :dbCursorName INTO
:proclog.PROC_ID,
:proclog.START_TS,
:proclog.END_TS:end_ts_ind,
:proclog.PROC_NAME:proc_name_ind,
:proclog.COMMENTS:comments_ind,
if (SQLCODE == 0)
printf("PROC_ID: %d; COMMENTS: %s\n",proclog.PROC_ID, proclog.COMMENTS);
} /* end retrieveProcesses */You need to include a loop...
for i=0;i<sqlca.sqlerrd[2];i++)
printf("name %s\n", struct.name)
This allows you to step through your cursor records!!! -
How do I use bin variable in package without asking a user?
hi,
I would like to write an SQL but I want to use bind variable in package as a static without asking user? Like below?
I would like to ask you, below there is a emp_id variable? Is this BIND variable?
DECLARE
bonus NUMBER(8,2);
emp_id NUMBER(6) := 100;
BEGIN
SELECT salary * 0.10 INTO bonus FROM employees
WHERE employee_id = emp_id;
END;
If not, like this SQL how can define a BIND variable as static inside a code? not asking a user?
db version. 9.2.0.8
regards and thanksOracleADay wrote:
I would like to ask you, below there is a emp_id variable? Is this BIND variable?
DECLARE
bonus NUMBER(8,2);
emp_id NUMBER(6) := 100;
BEGIN
SELECT salary * 0.10 INTO bonus FROM employees
WHERE employee_id = emp_id;
END;
/In the query "SELECT salary * 0.10 INTO bonus FROM employees WHERE employee_id = emp_id" emp_id is turned into a bind variable because
if you are coding static SQL in PL/SQL then PL/SQL wil automatically use bind variables: please read http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/overview.htm#sthref145.
This can also be proved with SQL trace. The following code:
alter session set sql_trace=true;
declare
v number;
c number;
begin
select count(*) into c
from t
where x=v;
end;
show errors
alter session set sql_trace=false;generates following raw trace file section with 10G XE:
=====================
PARSING IN CURSOR #2 len=79 dep=0 uid=69 oct=47 lid=69 tim=33338762257 hv=2860574766 ad='3c10120c'
declare
v number;
c number;
begin
select count(*) into c
from t
where x=v;
end;
END OF STMT
PARSE #2:c=46800,e=329811,p=0,cr=9,cu=0,mis=1,r=0,dep=0,og=1,tim=33338762253
=====================
PARSING IN CURSOR #1 len=35 dep=1 uid=69 oct=3 lid=69 tim=33338788761 hv=3539261652 ad='3c10053c'
SELECT COUNT(*) FROM T WHERE X=:B1
END OF STMT
PARSE #1:c=0,e=216,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=1,tim=33338788755
=====================Edited by: P. Forstmann on 17 mai 2011 17:47
Edited by: P. Forstmann on 17 mai 2011 17:55 -
How can I transfer a variable to regexp_replace function
Hi,
In addition to my question from yesterday, I went up one (little) level for the next question.
How can I transfer a variable to regexp_replace function?
I am getting the value of the variables from from APEX Items.
The value of item :P105_OLD_NAME should be replaced with the value from :P105_NAME APEX item.
The projects in PROJECT_NAME field are separated by “:”
select * from infoux_proj;
HOSTNAME PROJECT_NAME
host1 proj2:proj1
host3 proj1
host4 proj12:proj1
host5 proj3
host2 proj1:proj3:sunproj1
this is my code:
declare
v_old_proj_list varchar(100);
v_new_proj_list varchar(100);
begin
for host in (select a.hostname, project_name
from infoux_proj a,
(select hostname
from PROJECT_NAMES_WITH_HOSTNAMES
where name = :P105_OLD_NAME ) b
where a.HOSTNAME=b.hostname)
loop
select project_name ,
regexp_replace(project_name,'(^|:)(:P105_OLD_NAME)(:|$)','\1:P105_NAME \3') new_project
into v_old_proj_list, v_new_proj_list
from infoux_proj
where hostname=host.hostname;
update infoux_proj
set project_name=v_new_proj_list
where hostname=host.hostname;
end loop;
end;
Thanks,
SheliHi, Sheli
Inside quotes, :p105_old_name will not be taken as a variable name. If you want to use the value of :p105_old_name in a string which its otherwise a literal, then you can concatenate the variable to the literal parts, using the || operator.
You can do soemthing like this:
REGEXP_REPLACE ( project_name
, '(^|:)(' || :P105_OLD_NAME
|| ')(:|$)'
, '\1' || :P105_NAME
|| ' \3'
) AS new_projectI'll bet there's a much simpler way to do what you want. Instead of having two SELECTs, a cursor FOR loop and an UPDATE, you can probably do what you need to with just a single UPDATE or MERGE. It would be more efficient, too. If you'd like help, post CREATE TABLE and INSERT statements for all relevant tables and columns azs the exist before this code is run, a couple of sets of values for the bind variables, and the results you'd like to see (that is, the contents of the changed table) for each set, given the same sample data.
Always say which version of Oracle you're using. -
Cursor variable in a Java program
Hi all,
I would like to know is how to explicitly pass a cursor variable to a stored procedure after defining it in the java source and to get the result back to the same variable.
An example would be appreciated.
Thanks in advance
GiridharI think java profiler can do the job. There are sharewares i know of like JSprint and JProfiler.
-
How to determine the cursor record count before the "open cursor"?
Is it possible to determine the record count of an explicit cursor without running a count()? Say, my cursor definition is something like this,
CURSOR cur_vehicle
IS
SELECT os.order_id, os.order_item, vs.part_id
vs.part_num,
vs.iso_num,
vs.model_yr
vs.dealer_cde,
vs.cust_cde,
px.plant_cd
FROM parts_source vs,
orders_source os,
plant_tbl_crossref px
wHERE os.order_id = vs.order_id
AND vs.part_id = os.part_id
AND vs.plant_cde = px.plant_cde
ORDER BY os.order_id;
I want to log the count of records returned by the above cursor prior to the first fetch, without running a count(1) for the query in cursor select.
I know adding " Count(1) over(order by null) " in the cursor SELECT will bring it. But that does not help me log the record count to some log file or table before opening the cursor for processing.
To conclude, my objective is to update the record count of cursor in some table before processingsarvan wrote:
Is it possible to determine the record count of an explicit cursor without running a count()?
..snipped..No. The only way to do it correctly is inside that select.
Each select is a consistent read. Which means that if this is done as 2 select statements, the 1st select can see a different version of the data than the 2nd select statement. does. So if you want a count and that to be consistent and on the same version of the data than the select, it has to be done as part of the select.
Also consider what a cursor is. It is not a result set of sorts that is created in memory upfront - with a convenient interface that tells you the size/number of rows of that result set.
A cursor is basically a program that reads database data as input and produce output. A fetch from a cursor is an instruction for this program to execute and output data.
There's no data set that is created by the cursor from which the count can be determined. The cursor program does have state variables - like +%RowCount+ that specifies how many rows the cursor has thus far output. And you need to run that cursor to the end (no more output) in order to determine the total number of rows output by the cursor. -
Hello,
I have a procedure, which specification is something like that:
procedure proc1 (pcursor OUT SYS_REFCURSOR, parg1 IN NUMBER, parg2 IN NUMBER, ...);Inside the body of proc1 I have
OPEN pcursor FOR
SELECT column1,
column2,
CURSOR (SELECT column1, column2
FROM table2
WHERE <some clauses come here>) icursor1
FROM table1
WHERE <some clauses come here>;In a PL/SQL block I would like to execute proc1 and then to fetch from pcursor. This is what I am doing so far:
DECLARE
ldata SYS_REFCURSOR;
larg1 NUMBER := 123;
larg2 NUMBER := 456;
outcolumn1 dbms_sql.Number_Table;
outcolumn2 dbms_sql.Number_Table;
BEGIN
some_package_name.proc1 (ldata, larg1, larg2, ...);
FETCH ldata BULK COLLECT INTO
outcolumn1, outcolumn2,..., *and here is my problem*;
END;
/How can I rewrite this in order to get the content of icursor1 ?
Thanks a lot!Verdi wrote:
How can I rewrite this in order to get the content of icursor1 ?
Firstly ref cursors contain no data they are not result sets but pointers to compiled SQL statements.
Re: OPEN cursor for large query
PL/SQL 101 : Understanding Ref Cursors
Ref cursors are not supposed to be used within PL/SQL or SQL for that matter, though people keep on insisting on doing this for some reason.
http://download.oracle.com/docs/cd/E11882_01/appdev.112/e10472/static.htm#CIHCJBJJ
Purpose of Cursor Variables
You use cursor variables to pass query result sets between PL/SQL stored subprograms and their clients. This is possible because PL/SQL and its clients share a pointer to the work area where the result set is stored.A ref cursor is supposed to be passed back to a procedural client language, such as Java or .Net.
If you want to re-use a SQL statement in multiple other PL/SQL or SQL statements you would use a view. -
Cursor variable and for update
hi
can anyone explain me why can't we use "for update " with a Cursor Variable.
Thanks in advance.user10314274 wrote:
exmple : I read it in one book(Oracle press)And how difficult is it to test this?
declare
v_cur sys_refcursor;
v_ename varchar2(20);
begin
open v_cur for select ename from emp for update;
loop
fetch v_cur into v_ename;
exit when v_cur%notfound;
dbms_output.put_line(v_ename);
end loop;
close v_cur;
dbms_output.put_line('----------------------');
open v_cur for 'select ename from emp for update';
loop
fetch v_cur into v_ename;
exit when v_cur%notfound;
dbms_output.put_line(v_ename);
end loop;
close v_cur;
end;
SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER
SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER
PL/SQL procedure successfully completed.
SQL> SY. -
Migration Workbench Ver 1.2.2 has migrated an SQL Server 6.5
strored procedure as a package containing only the Cursor
variable and a procedure with INOUT parameter with packaged
cusorvariable as one of the parameters to Oracle 8.0.5.
How do you execute this procedure from SQL + and from another
PL/SQL block where you have to retrive the data elements of the
cursor.(ie.How do you input the cursor variable parameter in the
EXECUTE stored procedure command.)An example of the type is
appreciated.
nullSurendra,
Using refcursors between procedures is covered in the 'Wrong
number or types of argument in call to stored proc' 4 jun thread,
with reference to the manuals.
Using refcursor bind variables is covered in the sqlplus user
guide and reference reproduced below (from the 8.1.5 version,
also in 8.0.5) available on line on OTN.
Hope that helps,
Turloch
Oracle Migration Workbench Team
Using REFCURSOR Bind Variables
SQL*Plus REFCURSOR bind variables allow SQL*Plus to fetch and
format the results of a SELECT statement contained in a PL/SQL
block.
REFCURSOR bind variables can also be used to reference PL/SQL
cursor variables in stored procedures. This allows you to store
SELECT statements in the database and reference them from
SQL*Plus.
A REFCURSOR bind variable can also be returned from a stored
function.
Note:
You must have Oracle7, Release 7.3 or above to assign
the return value of a stored function to a
REFCURSOR variable.
Example 3-18 Creating, Referencing, and Displaying REFCURSOR Bind
Variables
To create, reference and display a REFCURSOR bind variable, first
declare a local bind variable of the REFCURSOR datatype
SQL> VARIABLE dept_sel REFCURSOR
Next, enter a PL/SQL block that uses the bind variable in an OPEN
... FOR SELECT statement. This statement opens a cursor variable
and executes a query. See the PL/SQL User's Guide and Reference
for information on the OPEN command and cursor variables.
In this example we are binding the SQL*Plus dept_sel bind
variable to the cursor variable.
SQL> BEGIN
2 OPEN :dept_sel FOR SELECT * FROM DEPT;
3 END;
4 /
PL/SQL procedure successfully completed.
The results from the SELECT statement can now be displayed in
SQL*Plus with the PRINT command.
SQL> PRINT dept_sel
DEPTNO DNAME LOC
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
The PRINT statement also closes the cursor. To reprint the
results, the PL/SQL block must be executed again before using
PRINT.
Example 3-19 Using REFCURSOR Variables in Stored Procedures
A REFCURSOR bind variable is passed as a parameter to a
procedure. The parameter has a REF CURSOR type. First, define the
type.
SQL> CREATE OR REPLACE PACKAGE cv_types AS
2 TYPE DeptCurTyp is REF CURSOR RETURN dept%ROWTYPE;
3 END cv_types;
4 /
Package created.
Next, create the stored procedure containing an OPEN ... FOR
SELECT statement.
SQL> CREATE OR REPLACE PROCEDURE dept_rpt
2 (dept_cv IN OUT cv_types.DeptCurTyp) AS
3 BEGIN
4 OPEN dept_cv FOR SELECT * FROM DEPT;
5 END;
6 /
Procedure successfully completed.
Execute the procedure with a SQL*Plus bind variable as the
parameter.
SQL> VARIABLE odcv REFCURSOR
SQL> EXECUTE dept_rpt(:odcv)
PL/SQL procedure successfully completed.
Now print the bind variable.
SQL> PRINT odcv
DEPTNO DNAME LOC
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
The procedure can be executed multiple times using the same or a
different REFCURSOR bind variable.
SQL> VARIABLE pcv REFCURSOR
SQL> EXECUTE dept_rpt(:pcv)
PL/SQL procedure successfully completed.
SQL> PRINT pcv
DEPTNO DNAME LOC
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
Example 3-20 Using REFCURSOR Variables in Stored Functions
Create a stored function containing an OPEN ... FOR SELECT
statement:
SQL> CREATE OR REPLACE FUNCTION dept_fn RETURN -
cv_types.DeptCurTyp IS2 resultset cv_types.DeptCurTyp;
3 BEGIN
4 OPEN resultset FOR SELECT * FROM DEPT;
5 RETURN(resultset);
6 END;
7 /
Function created.
Execute the function.
SQL> VARIABLE rc REFCURSOR
SQL> EXECUTE :rc := dept_fn
PL/SQL procedure successfully completed.
Now print the bind variable.
SQL> PRINT rc
DEPTNO DNAME LOC
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
4 rows selected
The function can be executed multiple times using the same or a
different REFCURSOR bind variable.
SQL> EXECUTE :rc := dept_fn
PL/SQL procedure successfully completed.
SQL> PRINT rc
DEPTNO DNAME LOC
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
Surendra Kumar (guest) wrote:
: Migration Workbench Ver 1.2.2 has migrated an SQL Server 6.5
: strored procedure as a package containing only the Cursor
: variable and a procedure with INOUT parameter with packaged
: cusorvariable as one of the parameters to Oracle 8.0.5.
: How do you execute this procedure from SQL + and from
another
: PL/SQL block where you have to retrive the data elements of the
: cursor.(ie.How do you input the cursor variable parameter in
the
: EXECUTE stored procedure command.)An example of the type is
: appreciated.
Oracle Technology Network
http://technet.oracle.com
null -
Hi all,
I have two different cursors of same recors.
create table temp_emp as select * from emp;
cursor cr_emp IS
select * from emp;
cursor cr_tmp IS
select * from temp_emp;
how to compare these two cursors.
Im trying to learn comparing cursors variables. I have oracle 11g, windows Vista.
Initially, I tried to compare only ename coloum:
create or replace procedure compare
IS
cursor cr_emp IS
select * from emp;
cursor cr_temp IS
select * from temp_emp;
v_cr_emp cr_emp%rowtype;
v_cr_temp cr_temp%rowtype;
emp_rownum integer;
tmpy_rownum integer;
V_CODE NUMBER;
V_ERRM VARCHAR2(64);
BEGIN
select MAX(rownum) into emp_rownum from emp;
select MAX(rownum) into tmpy_rownum from tmpy_emp;
open cr_emp;
open cr_temp;
FETCH CR_EMP INTO v_cr_emp;
FETCH CR_TEMP INTO v_cr_temp;
for emp_rownum in cr_emp
loop
for tmpy_rownum in cr_tmpy
loop
if(v_cr_emp.ename = v_cr_temp.ename)
then
dbms_output.put_line('equal');
else
dbms_output.put_line( 'not equal');
end if;
end loop;
end loop;
EXCEPTION
WHEN OTHERS
THEN
V_CODE := SQLCODE;
V_ERRM := SUBSTR(SQLERRM,1,64);
DBMS_OUTPUT.put_line ('ERROR CODE' || V_CODE || ':' || V_ERRM);
close cr_emp;
close cr_tmpy;
END;
SQL> start rain.sql
Procedure created.
SQL> exec compare
ERROR CODE-6511:ORA-06511: PL/SQL: cursor already open
PL/SQL procedure successfully completed.
Edited by: user10676396 on Apr 16, 2009 7:50 PMHi user10676396,
Hope this helps you understand the Nested loop, which I assumed you are trying to do in you program.
Note : Code not compiled and tested.
create or replace procedure compare
IS
cursor cr_emp IS
select * from emp;
cursor cr_temp IS
select * from temp_emp;
v_cr_emp cr_emp%rowtype;
v_cr_temp cr_temp%rowtype;
emp_rownum integer;
tmpy_rownum integer;
V_CODE NUMBER;
V_ERRM VARCHAR2(64);
BEGIN
select MAX(rownum) into emp_rownum from emp;
select MAX(rownum) into tmpy_rownum from tmpy_emp;
FOR REC IN cr_emp LOOP
dbms_output.put_line('For Ename in EMP : '||REC.ename ');
-- In FOR loops demo concept of nested loops
FOR TREC in cr_temp LOOP
if(REC.ename = TREC.ename)
then -- only output when you found a record in Temp
dbms_output.put_line('....EQUAL rec found in Temp : ' ||TREC.ename');
else
null ; -- Don't output if it is not equal
end if ;
END LOOP;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
V_CODE := SQLCODE;
V_ERRM := SUBSTR(SQLERRM,1,64);
DBMS_OUTPUT.put_line ('ERROR CODE' || V_CODE || ':' || V_ERRM);
close cr_emp;
close cr_tmpy;
END;
/Sanjay -
Dynamic SQL with cursor variables in pro*c
Please, what I need to do in order to be able
to do something like this:
EXEC SQL DECLARE :c CURSOR FOR :s;
In other words: I want to use variables
in cursor names.
Is it possible ? How ?
Thank you.OK. Here is an example of a Dynamic SQL #4 program I wrote several years ago (It's still running in production). It is currently running on a Sun E10K with Oracle 8.1.5. This code is JUST the pro*c part of a program which uses IBM MQ Series. MQ passes this program a Select SQL statement (as well as other parameters) as an argument. The Pro*c code allocates the structures, parses, and fetches, and executes the statement. I realize that this will not be easy to read. There are SOME comments in the code. However, I realize that to read anyone elses code is a chore. When you add Dynamic #4 to the list, it becomes much more complicated. Anyway, you'll probably need to copy and paste the code to a text file. It will be easier to read.
==========================================
Code
==========================================
| Program: mqsql.pc |
| Creator: Jim Wartnick |
| Purpose: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
| XXXXXXXXXXX |
| Date: 01/03/1997 |
| Modifications: |
#include"mqsql.h"
#define DEBUG
#ifdef DEBUG
FILE *fp=stdout;
#endif
int
disconnect_db() {
char msg[256], oraclmsg[256];
char buf[MAX_STRING_LENGTH+4];
int buf_len = 0, msg_len = 0;
EXEC SQL
COMMIT WORK RELEASE;
#ifdef DEBUG
fprintf(fp, " --> Disconnecting from database. RC: %d.\n", sqlca.sqlcode);
fflush(fp);
#endif
if (sqlca.sqlcode != 0) {
buf_len = sizeof(oraclmsg)-1;
sqlglm(oraclmsg, &buf_len, &msg_len);
oraclmsg[msg_len] = '\0';
error("disconnect_db()", "disconnect", sqlca.sqlcode, oraclmsg);
return(FAILURE);
return(SUCCESS);
int
connect_db() {
char msg[256], oraclmsg[256];
char buf[MAX_STRING_LENGTH+4];
int buf_len = 0, msg_len = 0;
char user[4];
strcpy(user, "/");
EXEC SQL
CONNECT :user;
#ifdef DEBUG
fprintf(fp, " --> Connecting to database. RC is %d\n", sqlca.sqlcode);
fflush(fp);
#endif
if (sqlca.sqlcode != 0) {
buf_len = sizeof(oraclmsg)-1;
sqlglm(oraclmsg, &buf_len, &msg_len);
oraclmsg[msg_len] = '\0';
sprintf(Results, "%9d", sqlca.sqlcode);
error("connect_db()", "connect", sqlca.sqlcode, oraclmsg);
return(FAILURE);
return(SUCCESS);
int
allocate_sqlda() {
| Initialize the SQLDA structure. |
| We only need the select descriptor |
| because we do not have any bind |
| variables. |
if ((Select_da = sqlald(
MAX_COLUMN_COUNT,
MAX_COLUMN_STRING_LENGTH,
MAX_INDICATOR_VARS
)) == (SQLDA *) 0) {
#ifdef DEBUG
fprintf(fp, " Memory allocation for Select Descriptor failed.\n");
fflush(fp);
#endif
strcpy(Results, "000000001");
error("allocate_sqlda()", "create SQLDA", 0, "Memory Error");
return(FAILURE);
#ifdef DEBUG
fprintf(fp, " Memory allocation for Select Descriptor succeeded.\n");
fflush(fp);
#endif
Select_da->N = MAX_COLUMN_COUNT;
return(SUCCESS);
int
prepare_sql() {
char msg[256], oraclmsg[256];
int buf_len = 0, msg_len = 0;
| Prepare the Sql statement. |
EXEC SQL
PREPARE sql_stmt
FROM :Sql;
#ifdef DEBUG
fprintf(fp, " Prepared SQL: %s. RC: %d.\n", Sql, sqlca.sqlcode);
fflush(fp);
#endif
if (sqlca.sqlcode != 0) {
buf_len = sizeof(oraclmsg)-1;
sqlglm(oraclmsg, &buf_len, &msg_len);
oraclmsg[msg_len] = '\0';
sprintf(Results, "%9d", sqlca.sqlcode);
error("prepare_sql()", "Parse", sqlca.sqlcode, oraclmsg);
return(FAILURE);
return(SUCCESS);
int
declare_cursor() {
char msg[256], oraclmsg[256];
int buf_len = 0, msg_len = 0;
| Set up the cursor to loop through |
EXEC SQL
DECLARE sql_cursor
CURSOR FOR sql_stmt;
#ifdef DEBUG
fprintf(fp, " Declared cursor. RC: %d\n", sqlca.sqlcode);
fflush(fp);
#endif
if (sqlca.sqlcode != 0) {
buf_len = sizeof( oraclmsg)-1;
sqlglm(oraclmsg, &buf_len, &msg_len);
oraclmsg[msg_len] = '\0';
sprintf(Results, "%9d", sqlca.sqlcode);
error("declare_cursor()", "declare cursor", sqlca.sqlcode, oraclmsg);
return(FAILURE);
return(SUCCESS);
int
open_cursor() {
char msg[256], oraclmsg[256];
int buf_len = 0, msg_len = 0;
| Open the cursor. |
EXEC SQL
OPEN sql_cursor;
#ifdef DEBUG
fprintf(fp, " Opened cursor. RC:%d\n", sqlca.sqlcode);
fflush(fp);
#endif
if (sqlca.sqlcode != 0) {
buf_len = sizeof(oraclmsg)-1;
sqlglm(oraclmsg, &buf_len, &msg_len);
oraclmsg[msg_len] = '\0';
sprintf(Results, "%9d", sqlca.sqlcode);
error("open_cursor()", "open cursor", sqlca.sqlcode, oraclmsg);
return(FAILURE);
return(SUCCESS);
int
describe_select_list() {
char msg[256], oraclmsg[256];
int buf_len = 0, msg_len = 0;
| Get description of columns |
EXEC SQL
DESCRIBE SELECT LIST FOR sql_stmt
INTO Select_da;
#ifdef DEBUG
fprintf(fp, " Described columns. RC %d\n", sqlca.sqlcode);
fflush(fp);
#endif
if (sqlca.sqlcode != 0) {
buf_len = sizeof(oraclmsg)-1;
sqlglm(oraclmsg, &buf_len, &msg_len);
oraclmsg[msg_len] = '\0';
sprintf(Results, "%9d", sqlca.sqlcode);
error("describe_select_list()", "describe select list", sqlca.sqlcode, oraclmsg);
return(FAILURE);
return(SUCCESS);
int
setup_sqlda() {
char buf[MAX_STRING_LENGTH+4];
int done = FALSE, nullok = 0, i = 0;
#ifdef DEBUG
fprintf(fp, " --> Setting up SQLDA.\n");
fflush(fp);
#endif
if (allocate_sqlda() == FAILURE)
return(FAILURE);
if (prepare_sql() == FAILURE)
return(FAILURE);
if (declare_cursor() == FAILURE)
return(FAILURE);
if (open_cursor() == FAILURE)
return(FAILURE);
if (describe_select_list() == FAILURE)
return(FAILURE);
| Too many columns in select list. |
if (Select_da->F < 0) {
strcpy(Results, "000000001");
error("setup_sqlda()", "check select list count", 0, "Too many values in select list");
return(FAILURE);
| Set the number of columns to the actual |
| number of columns. |
Select_da->N = Select_da->F;
| We are going to convert all fields to a string. |
for (i == 0; i < Select_da->F; i++) {
sqlnul(&(Select_da->T), &(Select_da->T[i]), &nullok);
Select_da->T[i] = EXT_STRING;
Select_da->L[i] = MAX_STRING_LENGTH;
| Allocate the result area to be as big as |
| MAX_STRING_LENGTH. |
if ((Select_da->V[i] = malloc(Select_da->L[i])) == NULL) {
#ifdef DEBUG
fprintf(fp, " Allocation of column values failed.\n");
fflush(fp);
#endif
strcpy(Results, "000000001");
error("setup_sqlda()", "allocate column values", 0, "Memory Error");
return(FAILURE);
if ((Select_da->I[i] = (short *) malloc(sizeof(short))) == NULL) {
#ifdef DEBUG
fprintf(fp, " Allocation of idicator values failed.\n");
fflush(fp);
#endif
strcpy(Results, "000000001");
error("setup_sqlda()", "allocate indicator values", 0, "Memory Error");
return(FAILURE);
#ifdef DEBUG
fprintf(fp, " Allocation of memory for values succeeded.\n");
fflush(fp);
#endif
return(SUCCESS);
| add_eom adds the end of message |
| delimiter (an aditional comma). |
int
add_eom() {
char *result_ptr;
if (strlen(Results) >= sizeof(Results) - 1) {
strcpy(Results, "000000001");
error("add_eom()", "Add eom failed. Size overflow", 0, "Memory Error");
return(FAILURE);
result_ptr = &Results[strlen(Results)-1];
while (*result_ptr && (*result_ptr != ','))
result_ptr--;
if (*result_ptr) {
result_ptr++;
*(result_ptr++) = ',';
*result_ptr = '\0';
return(SUCCESS);
int close_cursor() {
char msg[256], oraclmsg[256];
int buf_len = 0, msg_len = 0;
| Close the cursor. |
EXEC SQL
CLOSE sql_cursor;
#ifdef DEBUG
fprintf(fp, " Closing cursor. RC: %d\n", sqlca.sqlcode);
fflush(fp);
#endif
if (sqlca.sqlcode != 0) {
buf_len = sizeof(oraclmsg)-1;
sqlglm(oraclmsg, &buf_len, &msg_len);
oraclmsg[msg_len] = '\0';
error("generate_sql()", "close cursor", sqlca.sqlcode, oraclmsg);
return(FAILURE);
return(SUCCESS);
int
fetch() {
char msg[256], oraclmsg[256];
char buf[MAX_STRING_LENGTH+4];
int buf_len = 0, msg_len = 0;
EXEC SQL
FETCH sql_cursor
USING DESCRIPTOR Select_da;
#ifdef DEBUG
fprintf(fp, " --> Fetching rows. RC %d\n", sqlca.sqlcode);
fflush(fp);
#endif
if (sqlca.sqlcode != 0) {
if (sqlca.sqlcode != NODATAFOUND) {
buf_len = sizeof(oraclmsg)-1;
sqlglm(oraclmsg, &buf_len, &msg_len);
oraclmsg[msg_len] = '\0';
error("fetch()", "Error fetching row.", sqlca.sqlcode, oraclmsg);
return(sqlca.sqlcode);
return(NODATAFOUND);
return(SUCCESS);
| Free up any memory structures. |
void
free_memory() {
int i = 0;
for (i = 0; i < Select_da->F; i++) {
free(Select_da->V[i]);
free(Select_da->I[i]);
| generate_sql() uses the message we received from the queue |
| (a SQL statement) to query the database. We have to use |
| dynamic Sql Version 4 for this type of Sql. The number of |
| columns we are selecting is unknown. This means we can't |
| use the INTO clause. |
int
generate_sql() {
char buf[MAX_STRING_LENGTH+4];
int rc = SUCCESS, done = FALSE, nullok = 0, i = 0;
#ifdef DEBUG
if ((fp = fopen(SQLLOG, "a")) == NULL)
fp = stderr;
#endif
| Connect to the database |
if (connect_db() == FAILURE)
return(FAILURE);
if (setup_sqlda() == FAILURE)
return(FAILURE);
| Place the answer in a comma delimited buffer. |
memset(Results, NULL, sizeof(Results));
done = FALSE;
while (!done) {
rc = fetch();
if (rc != SUCCESS) {
if (Results[0] == '\0')
sprintf(Results, "%9d,", rc);
done = TRUE;
else {
| Put return code of success in first. |
if (Results[0] == '\0')
strcpy(Results, "000000000,");
for (i = 0; i < Select_da->F; i++) {
Select_da->V[i][Select_da->L[i]] = '\0';
| Check to see if the value is null. |
if (*Select_da->I[i] < 0)
strcpy(buf, " ,");
else
sprintf(buf, "%s,", Select_da->V[i]);
if (strlen(Results) + strlen(buf) > sizeof(Results)) {
strcpy(Results, "000000001");
error("generate_sql()", "String concat failed. Size overflow", 0, "Memory Error");
return(FAILURE);
strcat(Results, buf);
#ifdef DEBUG
fprintf(fp, " --> Results %s\n", Results);
fflush(fp);
#endif
| Close the cursor. |
close_cursor();
| Disconnect from the database |
disconnect_db();
| Remove trailing comma. |
if (add_eom() == FAILURE)
return(FAILURE);
#ifdef DEBUG
fflush(fp);
#endif
free_memory();
#ifdef DEBUG
fclose(fp);
#endif
null -
Cursor Variable in Nested Block
Dear all,
I have a package that has procedures that open cursor variables and print the queries of sample schema HR. There's one procedure that opens the cursor with an input integer to choose which query that wants to be fetched. The other prints the query by fetching the cursor in a nested block with exceptions. The following package runs as intended, it prints all the three options without any problems:
CREATE OR REPLACE PACKAGE admin_data AS
TYPE gencurtyp IS REF CURSOR;
PROCEDURE open_cv (generic_cv IN OUT gencurtyp, choice INT);
procedure print_cv (generic_cv gencurtyp);
END admin_data;
CREATE OR REPLACE PACKAGE BODY admin_data AS
PROCEDURE open_cv (generic_cv IN OUT gencurtyp, choice INT) IS
BEGIN
IF choice = 1 THEN
OPEN generic_cv FOR SELECT * FROM jobs where job_id='ST_MAN';
ELSIF choice = 2 THEN
OPEN generic_cv FOR SELECT * FROM departments where department_id=270;
ELSIF choice = 3 THEN
OPEN generic_cv FOR SELECT * FROM employees where employee_id=206;
END IF;
END;
procedure print_cv (generic_cv gencurtyp)is
employees_rec employees%rowtype;
departments_rec departments%rowtype;
jobs_rec jobs%rowtype;
begin
fetch generic_cv into jobs_rec;
dbms_output.put_line(jobs_rec.job_title);
exception
when ROWTYPE_MISMATCH then
begin
fetch generic_cv into departments_rec;
dbms_output.put_line(departments_rec.department_name);
exception
when ROWTYPE_MISMATCH then
dbms_output.put_line('row mismatch');
fetch generic_cv into employees_rec;
dbms_output.put_line(employees_rec.first_name);
when OTHERS then
dbms_output.put_line('others');
fetch generic_cv into employees_rec;
dbms_output.put_line(employees_rec.first_name);
end;
end print_cv;
END admin_data;
declare
some_cur admin_data.gencurtyp;
begin
admin_data.open_cv(some_cur,1);
admin_data.print_cv(some_cur);
admin_data.open_cv(some_cur,2);
admin_data.print_cv(some_cur);
admin_data.open_cv(some_cur,3);
admin_data.print_cv(some_cur);
admin_data.open_cv(some_cur,3);
admin_data.print_cv(some_cur);
admin_data.open_cv(some_cur,1);
admin_data.print_cv(some_cur);
admin_data.open_cv(some_cur,2);
admin_data.print_cv(some_cur);
end;
17 /
Stock Manager
Payroll
row mismatch
William
row mismatch
William
Stock Manager
Payroll
PL/SQL procedure successfully completed.The innermost block executes 'rowtype mismatch' exception block, which fetches
SELECT * FROM employees where employee_id=206 query.
This time, I switch the query fetch so that
SELECT * FROM employees where employee_id=206query is in the outermost block and
SELECT * FROM jobs where job_id='ST_MAN' is in the innermost block. The package body looks like this:
CREATE OR REPLACE PACKAGE BODY admin_data AS
PROCEDURE open_cv (generic_cv IN OUT gencurtyp, choice INT) IS
BEGIN
IF choice = 1 THEN
OPEN generic_cv FOR SELECT * FROM jobs where job_id='ST_MAN';
ELSIF choice = 2 THEN
OPEN generic_cv FOR SELECT * FROM departments where department_id=270;
ELSIF choice = 3 THEN
OPEN generic_cv FOR SELECT * FROM employees where employee_id=206;
END IF;
END;
procedure print_cv (generic_cv gencurtyp)is
employees_rec employees%rowtype;
departments_rec departments%rowtype;
jobs_rec jobs%rowtype;
begin
fetch generic_cv into employees_rec;
dbms_output.put_line(employees_rec.first_name);
exception
when ROWTYPE_MISMATCH then
begin
fetch generic_cv into departments_rec;
dbms_output.put_line(departments_rec.department_name);
exception
when ROWTYPE_MISMATCH then
dbms_output.put_line('row mismatch');
fetch generic_cv into jobs_rec;
dbms_output.put_line(jobs_rec.job_title);
when OTHERS then
dbms_output.put_line('others');
fetch generic_cv into jobs_rec;
dbms_output.put_line(jobs_rec.job_title);
end;
end print_cv;
END admin_data;
then I run the same anonymous block, I get:declare
some_cur admin_data.gencurtyp;
begin
admin_data.open_cv(some_cur,1);
admin_data.print_cv(some_cur);
admin_data.open_cv(some_cur,2);
admin_data.print_cv(some_cur);
admin_data.open_cv(some_cur,3);
admin_data.print_cv(some_cur);
admin_data.open_cv(some_cur,3);
admin_data.print_cv(some_cur);
admin_data.open_cv(some_cur,1);
admin_data.print_cv(some_cur);
admin_data.open_cv(some_cur,2);
admin_data.print_cv(some_cur);
end;
17 /
others
Payroll
William
William
others
Payroll
PL/SQL procedure successfully completed.
The strangest thing is the innermost block execute OTHERS exception block instead of ROWTYPE MISMATCH and the the record doesn't fetch anything. What happen? How come the result is different when I only switch the query?
Best regards,
ValHi Sy,
thanks for the reply, yes I agree that the code is cumbersome, I'm studying to prepare OCP PL/SQL certification, so I'm playing around with cursor variable in order to grasp the whole concept. I'm observing the behaviour of weak cursor variable when getting passed into a function and fetched couple of times and exploring exception propagation in the same time. This why the code looks not relevant in the real world.
Anyway, I just curious how it behaves like that. Here's my instance info:
SQL> select * from v$version
2 ;
BANNER
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production -
PL/SQL column names in cursor variable
Hi,
I try to put all column names of a table in a cursor variable?? without the values, just the column names.
Can somebody help me, because I really don't know how to do this.
Thanks,
MoniHi Jes,
my table looks like this: T1
columnNames: id | col1 | col2 | col3 | col4 | col5
Values: a | b | c| d| e| f
the number of the columns depend on a how many rows in another table (T2) are entered. If a new row is entered in T2, I have to add a column in table T1.
and then I have to look what is the new row, compare it with all my existing columnnames in T1 and add the right one.
my vector should look like this:
c1:
id
col1
col2
col3
col4
col5
I hope you know what I mean, it is not very easy to describe!
Thanks for helping me!
Moni
Maybe you are looking for
-
Hi, I have the following: Lenovo ThinkStation S20 Xeon W3550 Quad-Core Processor (3.06GHz 1066MHz 8MB) 4gb (2 x 2gb) udimm ddr3 1333MHz, 300GB SAS (15k) with SAS Controller Card NVIDIA Quadro 2000 I would like to add more memory, and would like to kn
-
Asset Report by Vendor/Manufacturer #
Hi, Is there a standard SAP asset report with the field of vendor and manufacturer #? Thanks, Teo
-
Using the env variable of unix in a procedure call
hi, how can i use the environment varible of unix in a oracle procedure call ? I am working woth shell scripts and it hold some value into a variable and that varible value I want to pass into a oracle procedure. i'm sending the sample code and pleas
-
My WRT54G v5 router loses internet connection frequently
My WRT54G v5 router loses internet connection frequently. Sometimes occurs when you enter a web or sometimes every few minutes, but without a pattern. I have W XP Pro with SP3 and I have a pc wired to the router and sometimes 2 notebook with Wi-Fi. W
-
How can i insert the plugin internet to see many web page
how can i insert on my mac book pro the plugin internet , necessary to see many web site