how to fetch cursor values into an object - oracle

I want to fetch values from a cursor and store them in an object....
I tried doing the same with Record i got the output
DECLARE
CURSOR lc_emp_fetch
IS
SELECT emp_no,emp_name FROM maniemp;
TYPE r_emp_record IS RECORD (
eno maniemp.emp_no%TYPE,
ename maniemp.emp_name%TYPE
);
TYPE t_emp IS TABLE OF r_emp_record;
lt_emp_rcd t_emp;
BEGIN
OPEN lc_emp_fetch;
LOOP
FETCH lc_emp_fetch BULK COLLECT INTO lt_emp_rcd LIMIT 5;
EXIT WHEN lt_emp_rcd.COUNT=0;
FOR indx IN 1..lt_emp_rcd.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(lt_emp_rcd(indx).eno||lt_emp_rcd(indx).ename);
END LOOP;
END LOOP;
CLOSE lc_emp_fetch;
END;
/
but when i try doing the same in an object its not working... i surfed all the websites but didn't get proper example program. This is my object:
CREATE OR REPLACE TYPE Typename3 AS OBJECT (
eno number,
ename varchar2(500),
esal number);
SHOW ERRORS;
I am new to this i don't know how to do this can someone help me with this

If you want to try the above example with an object and type then you should create both are at schema level it means
CREATE OR REPLACE type R_EMP_OBJECT as object(
eno number,
ename varchar2(30)
);
and
`create or replace type t_emp IS TABLE OF r_emp_object`;
then
DECLARE
lt_emp_rcd t_emp;
BEGIN
select r_emp_object (emp,ename) bulk collect into lt_emp_rcd
FROM emp;
FOR indx IN 1..lt_emp_rcd.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(lt_emp_rcd(indx).eno||lt_emp_rcd(indx).ename);
END LOOP;
END;
Edit I have tried with cursors, the below code is working fine
DECLARE
CURSOR C1
IS
SELECT emp_no,emp_name FROM maniemp;
C2 C1%ROWTYPE;
LT_EMP_RCD T_EMP;
BEGIN
OPEN C1;
LOOP
FETCH C1 INTO C2 ;
SELECT R_EMP_OBJECT(C2.EMP_NO,C2.EMP_NAME) BULK COLLECT INTO LT_EMP_RCD FROM DUAL;
EXIT WHEN C1%NOTFOUND;
FOR INDX IN 1..LT_EMP_RCD.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(LT_EMP_RCD(INDX).ENO||' '||LT_EMP_RCD(INDX).ENAME);
END LOOP;
END LOOP;
CLOSE C1;
END;

Related

How can i select data from table of %ROWTYPE to refcursor?

declare
cursor cur0 is Select no, date from data123;
TYPE TempTabTyp0 is table of cur0%ROWTYPE index by pls_integer;
temp_tab0 TempTabTyp0;
lrc sys_refcursor;
BEGIN
open cur0;
fetch cur0 bulk collect into temp_tab0;
close cur0;
for rec in 1 .. temp_tab0.count loop
temp_tab0(rec).no := 'new value' || temp_tab0(rec).no;
end loop;
open lrc for select * from table(temp_tab0);
END;
How can i send data from temp_tab0 to sys_refcursor (or another cursor)?
Just wrap your code in a package. Something like this:
create table data123 (no, dt) as
select cast ('abc' as varchar2 (30)), date'2020-09-20' from dual
/
create or replace package pack1 as
cursor cur0 is select no, dt from data123;
type TempTabTyp0 is table of cur0%rowtype index by pls_integer;
procedure getcur (rc out sys_refcursor);
end;
/
create or replace package body pack1 as
procedure getcur (rc out sys_refcursor) is
temp_tab0 TempTabTyp0;
begin
open cur0;
fetch cur0 bulk collect into temp_tab0;
close cur0;
for i in 1..temp_tab0.count loop
temp_tab0(i).no := 'new value '||temp_tab0(i).no;
end loop;
open rc for select * from table (temp_tab0);
end;
end;
/
Executing and result:
var rc refcursor
exec pack1.getcur (:rc)
ATTR_1 ATTR_2
------------------------------ -------------------
new value abc 2020-09-20 00:00:00
PS for incorrect output headings see this topic.

Cursor in pl/sql

I have ORACLE class airport_t that has data fields for
Rank,
Airport,
Location,
Country,
Code_IATA,
Code_ICAO,
Total_passenger,
Rank_change,
Percent_Change
I created table AIRPORTS2017OO that has one single column AIRPORT, which can store an object of type airport_t. I have 50 rows of data in Airport2017 table which I to insert into airport column of table AIRPORTS2017OO using cursor.
I am able to iterate through airports2017 table through cursor given below, but I do not know how to insert data into AIRPORTS2017OO table.
Here is my solution of getting all info from airports2017 table
DECLARE
rank1 NUMBER;
airports1 VARCHAR2 (80);
location1 VARCHAR (40);
country1 VARCHAR (30);
iata1 VARCHAR (3);
icao1 VARCHAR (4);
total_pass NUMBER;
rank_c NUMBER;
p_change NUMBER;
CURSOR display
IS
SELECT * FROM airports2017;
BEGIN
OPEN display;
LOOP
FETCH display
INTO rank1,
airports1,
location1,
country1,
iata1,
icao1,
total_pass,
rank_c,
p_change;
IF display%FOUND
THEN
DBMS_OUTPUT.put_line (airports1);
ELSE
EXIT;
END IF;
END LOOP;
CLOSE display;
END;
/
You do know that you can do:
INSERT INTO AIRPORTS2017OO select * from airports2017;
instead of all this cursor code right?
Anyway here's how to do it:
DECLARE
a_data ARRAY;
CURSOR display
IS
SELECT * FROM airports2017;
BEGIN
OPEN display;
LOOP
FETCH display BULK COLLECT INTO a_data;
FORALL i IN 1..a_data.COUNT
INSERT INTO AIRPORTS2017OO VALUES a_data(i);
IF display%FOUND
THEN
DBMS_OUTPUT.put_line (airports1);
ELSE
EXIT;
END IF;
END LOOP;
CLOSE display;
END;
/

ORA-06504: PL/SQL: Return types of Result Set variables while execution

I created an Object and procedure as below and while execution i get the below error.
ORA-06504: PL/SQL: Return types of Result Set variables or query do
not match ORA-06512: at line 8
CREATE OR REPLACE TYPE OBJ_TST AS OBJECT
(
COl_ID NUMBER (30, 0),
Col_DATE TIMESTAMP (6)
);
/
create or replace TYPE OBJ_TBL AS TABLE OF OBJ_TST;
/
CREATE OR REPLACE PROCEDURE TST_OBJ (input_date IN DATE,
out_cur OUT SYS_REFCURSOR )
AS
l_tab OBJ_TBL := OBJ_TBL ();
BEGIN
SELECT OBJ_TST (ti.col_id, ti.col_date)
BULK COLLECT INTO l_tab
FROM MY_TBL ti
WHERE ti.create_date BETWEEN input_date AND input_date + 1;
Open o_cur for select col_id,col_date from table(l_tab);
END TST_OBJ;
/
Execution brings me the above mentioned error. MY_TBL has column data type of (col_id and col_date) same as of my object.
DECLARE
a SYS_REFCURSOR;
var1 OBJ_TBL;
BEGIN
TST_OBJ (input_date => '21-Aug-2017', out_cur => a);
FETCH a bulk collect INTO var1;
For rec in 1..var1.count
LOOP
DBMS_OUTPUT.put_line (var1(rec).col_id ||' '|| var1(rec).Col_DATE);
END LOOP;
END;
/
ORA-06504: PL/SQL: Return types of Result Set variables or query do
not match ORA-06512: at line 8
However when i excute like this it works fine:
DECLARE
a SYS_REFCURSOR;
var1 NUMBER;
var2 TIMESTAMP (6);
BEGIN
TST_OBJ (i_date => '21-Aug-2017', out_cur => a);
LOOP
FETCH a INTO var1, var2;
EXIT WHEN a%NOTFOUND;
DBMS_OUTPUT.put_line (var1 ||' '|| var2);
END LOOP;
END;
Can anyone please suggest whats wrong here ?
You're using a table collection expression to unnest your table collection:
Open out_cur for select col_id,col_date from table(l_tab);
The query is returning two relational columns, not a single object, so your cursor has two columns too. Trying to bulk collect two relational columns into a single object in your anonymous block is throwing the exception.
You could, I suppose, recombine them as objects:
Open out_cur for select OBJ_TST(col_id,col_date) from table(l_tab);
or if you don't want to explicitly list the column/field names:
Open out_cur for select cast(multiset(select * from table(l_tab)) as obj_tbl) from dual;
But then in your example having the table type is a bit pointless, and you can just do:
CREATE OR REPLACE PROCEDURE TST_OBJ (input_date IN DATE,
out_cur OUT SYS_REFCURSOR )
AS
BEGIN
Open out_cur for
SELECT OBJ_TST (ti.col_id, ti.col_date)
FROM MY_TBL ti
WHERE ti.create_date BETWEEN input_date AND input_date + 1;
END TST_OBJ;
/
But I image you have some other use for the collection inside the function - modifying it before querying and returning it. Or you could make the second argument of OBJ_TBL type instead of a ref cursor, so the caller doesn't have to bulk collect that into its own local collection itself.
DECLARE
a SYS_REFCURSOR;
var1 OBJ_TBL;
BEGIN
TST_OBJ (input_date => '21-Aug-2017', out_cur => a);
FETCH a bulk collect INTO var1;
For rec in 1..var1.count
LOOP
DBMS_OUTPUT.put_line (var1(rec).col_id ||' '|| var1(rec).Col_DATE);
END LOOP;
END;
/
The cursor a has two columns and you are trying to bulk collect them into a single variable. Oracle will not wrap them in a OBJ_TST object and it can't match them.
Why use cursors at all:
CREATE OR REPLACE PROCEDURE TST_OBJ (
input_date IN DATE,
out_objs OUT OBJ_TBL
)
AS
BEGIN
SELECT OBJ_TST( col_id, col_date)
BULK COLLECT INTO out_objs
FROM MY_TBL
WHERE create_date BETWEEN input_date AND input_date + 1;
END TST_OBJ;
/
Then you can just do:
DECLARE
var1 OBJ_TBL;
BEGIN
TST_OBJ (
input_date => DATE '2017-08-21',
out_objs => var1
);
For rec in 1..var1.count LOOP
DBMS_OUTPUT.put_line (var1(rec).col_id ||' '|| var1(rec).Col_DATE);
END LOOP;
END;
/

How to store a column of result of select query in an array?

If we have a column in a table of type number, how can we store the result of select query on that column in an array ?
This sample uses a list (table of numbers) to achieve this, because i find
those lists much more handy:
CREATE OR REPLACE TYPE numberlist AS TABLE OF NUMBER;
DECLARE
v_numberlist numberlist;
BEGIN
SELECT intval numbercolumn
BULK COLLECT INTO v_numberlist
FROM lookup;
FOR i IN 1..v_numberlist.count
LOOP
dbms_output.put_line( v_numberlist(i) );
END LOOP;
END;
Create a type which store number:-
CREATE OR REPLACE TYPE varray is table of number;
--write your select query inside for loop () where i am extracting through level
declare
p varray := varray();
BEGIN
for i in (select level from dual connect by level <= 10) loop
p.extend;
p(p.count) := i.level;
end loop;
for xarr in (select column_value from table(cast(p as varray))) loop
dbms_output.put_line(xarr.column_value);
end loop;
END;
output:-
1
2
3
4
5
6
7
8
9
10
Just an option to use some native SQL datatype. Hope it helps.
SET SERVEROUTPUT ON;
DECLARE
lv_num_tab DBMS_SQL.NUMBER_TABLE;
BEGIN
SELECT LEVEL BULK COLLECT INTO lv_num_tab FROM DUAL CONNECT BY LEVEL < 10;
FOR I IN lv_num_tab.FIRST..lv_num_tab.LAST
LOOP
dbms_output.put_line(lv_num_tab(i));
END LOOP;
END;
You may also want to put the whole select in a table. You can use a BULK COLLECT to an array:
CREATE OR REPLACE TYPE t_my_list AS TABLE OF VARCHAR2(100);
CREATE OR REPLACE
PROCEDURE get_tables(p_owner in varchar2)
as
v_res t_my_list;
v_qry varchar2(4000) := '';
begin
v_qry := ' SELECT table_name from all_tables where owner='''||p_owner||'''';
dbms_output.put_line(v_qry);
-- all at once in the table
execute immediate v_qry bulk collect into v_res;
FOR I in 1..v_res.count
loop
dbms_output.put_line(v_res(i));
end loop;
exception
when others then
raise;
end get_tables;
/
begin
get_tables('E') ;
end;
/

How to fetch the cursor data in oracle stored procedure

create or replace
PROCEDURE get_new
AS
CUST_ID varchar2(100);
ROUTERNAME_N VARCHAR2(100);
BEGIN
CURSOR c1 IS
SELECT TRAFFIC_CUST_ID,ROUTERNAME INTO CUST_ID,ROUTERNAME_N
FROM INTERFACE_ATTLAS
WHERE rownum > 3;
my_ename INTERFACE_ATTLAS.TRAFFIC_CUST_ID%TYPE;
my_salary INTERFACE_ATTLAS.ROUTERNAME%TYPE;
LOOP
FETCH c1 INTO my_ename;
FETCH c1 INTO my_salary;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(my_ename);
end loop;
end;
I am new to oracle and stored procedure. I am trying to get the rows using cursor fetch, and getting following error:
PLS-00103: Encountered the symbol "C1" when expecting one of the following:
:= . ( # % ;
Rewrite it like this:
create or replace
PROCEDURE get_new
AS
my_ename INTERFACE_ATTLAS.TRAFFIC_CUST_ID%TYPE;
my_salary INTERFACE_ATTLAS.ROUTERNAME%TYPE;
CURSOR c1 IS
SELECT TRAFFIC_CUST_ID,ROUTERNAME
FROM INTERFACE_ATTLAS
WHERE rownum > 3;
BEGIN
open c1;
LOOP
FETCH c1 INTO my_ename, my_salary;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(my_ename);
end loop;
close c1;
end;
Do not forget to open and close cursors. It always will print nothing because of rownum > 3; You wanted to type: rownum < 3;, didn't you?
create or replace
PROCEDURE get_new
AS
CUST_ID varchar2(100);
ROUTERNAME_N VARCHAR2(100);
BEGIN
CURSOR c1 IS
SELECT TRAFFIC_CUST_ID,ROUTERNAME INTO CUST_ID,ROUTERNAME_N
FROM INTERFACE_ATTLAS
WHERE rownum > 3;
my_ename INTERFACE_ATTLAS.TRAFFIC_CUST_ID%TYPE;
my_salary INTERFACE_ATTLAS.ROUTERNAME%TYPE;
LOOP
FETCH c1 INTO my_ename;
FETCH c1 INTO my_salary;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(my_ename);
end loop;
end;
Cursor should be declare in the declaration part. Then have to open in begin-end section. In the declaration section you can not assign value to variable. When you are fetching value you can not select randomly value form cursor,
modified code:
create or replace
PROCEDURE get_new
AS
no mean --CUST_ID varchar2(100);
no means -- ROUTERNAME_N VARCHAR2(100);
CURSOR c1 IS
SELECT deptno,job
FROM emp;
my_ename emp.deptno%TYPE;
my_salary emp.job%TYPE;
BEGIN
open c1;
LOOP
fetch c1 into my_ename,my_salary;
-- FETCH c1 INTO my_ename;
--FETCH c1 INTO my_salary;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(my_ename);
end loop;
end;
execute get_new.
You should probably declare your cursor and your variables my_ename and my_salary in the dedicated section, i.e. before the BEGIN, and then open your cursor:
IS
CUST_ID varchar2(100);
ROUTERNAME_N VARCHAR2(100);
C1 sys_refcursor;
my_ename INTERFACE_ATTLAS.TRAFFIC_CUST_ID%TYPE;
my_salary INTERFACE_ATTLAS.ROUTERNAME%TYPE;
BEGIN
OPEN C1 for
SELECT ...
You would have to declare the Cursor before BEGIN. You would use no INTO clause in the cursor declaration. Then you would have to OPEN the cursor. Then you would FETCH INTO my_ename, my_salary, not one after the other (you fetch rows, not columns). WHERE rownum > 3 returns no rows. As you don't want a first row, you will never get a second, third and fourth either.
And you can use an implicit cursor which is easier to deal with (no need to open, fetch and close explicitely):
BEGIN
FOR rec IN
(
select traffic_cust_id, routername
from interface_attlas
where rownum <= 3
) LOOP
DBMS_OUTPUT.PUT_LINE(rec.traffic_cust_id || ': ' || rec.salary);
END LOOP;
END;

Resources