CASTing Table Type to Cursor
Hi,
I have req. that A proc is calling B proc which in turn return me a set of records in table type. Then i manipulate the data in A proc and i want to return this set in cursor type.
could you please help me. here i have pasted my example.
CREATE OR REPLACE TYPE oemp AS OBJECT
eno number(4),
enm varchar2(10),
sal number(7,2)
CREATE OR REPLACE TYPE temp AS TABLE OF oemp;
Proc B:=
procedure showemp( dno in number, disp out temp)
is
l_str varchar2(1000);
begin
l_str := 'select oemp(empno, ename, sal) from emp where deptno = :dno';
execute immediate l_str
bulk collect into disp
using dno;
exception
when no_data_found then
null;
end;
CREATE OR REPLACE TYPE odemp AS OBJECT
eno number(4),
enm varchar2(10),
sal number(7,2),
com number(7,2)
proc A:
procedure showempdet_cur(idno in number, oshow out cursor_type)
is
ishow temp;
type tde is table of odemp;
o_emp tde := tde();
begin
--Call to Proc A
showemp(idno, ishow);
if ishow.count > 0 then
for i in ishow.first..ishow.last loop
o_emp.extend;
o_emp(o_emp.last) := odemp(ishow(i).eno, ishow(i).enm, ishow(i).sal, ishow(i).sal * .1);
end loop;
end if;
-- here I want to return this o_emp table outside as cursor type
-- i want to use this proc in crystal report which does not accept table type
--return type
end;
hope this will help..I was trying to use CAST with MULTISET option..but some where i am doing wrong..
help will appreciated.
Thanks
RSD
You can query only sql-collections.
SQL> create or replace type table_of_odemp as table of odemp;
SQL> /
Type created.
SQL>
SQL> var c refcursor
SQL>
SQL> declare
SQL> o_emp table_of_odemp := table_of_odemp();
SQL> begin
SQL> for i in 1..5 loop
SQL> o_emp.extend;
SQL> o_emp(o_emp.last) := odemp(i, 'Name'||i, i*1000, i*50);
SQL> end loop;
SQL> open :c for select * from table(cast(o_emp as table_of_odemp));
SQL> end;
SQL> /
PL/SQL procedure successfully completed.
SQL>
SQL> print c
ENO ENM SAL COM
1 Name1 1000 50
2 Name2 2000 100
3 Name3 3000 150
4 Name4 4000 200
5 Name5 5000 250
Similar Messages
-
I am storing data in a table type.I want to return cursor type to .net code.
Can i convert this table type to cursor.
Here is my code
DECLARE
v_FamilyMember VARCHAR2(20);
v_counter number default 0;
TYPE NameTab IS TABLE OF varchar2(20)
INDEX BY BINARY_INTEGER;
v_Names NameTab;
CURSOR c_Family IS
select distinct
case when pr.relationship_cd IN (01,02,04,05) Then 'Child'
when pr.relationship_cd IN (03,09,10) Then 'spouse'
when pr.relationship_cd IN (00,'',null) then 'subscriber'
end as AssesmentResult
from
employee_coverage_level ecl inner join member_benefit_selection mbs
on
ecl.cust_id = mbs.cust_id and ecl.platform_cd = mbs.platform_cd
and ecl.platform_group_nbr = mbs.platform_group_nbr and ecl.ben_id = mbs.ben_id
and ecl.ben_date = mbs.ben_date and ecl.pers_key = mbs.pers_key
inner join person_relationship pr on pr.from_pers_key = mbs.pers_key and pr.pers_key = mbs.mbr_pers_key
where
ecl.pers_key = 343528 and
ecl.cust_id = 1239 and ecl.class_nbr = 211 order by AssesmentResult asc;
BEGIN
OPEN c_Family;
LOOP
FETCH c_Family INTO v_FamilyMember;
EXIT WHEN c_Family%NOTFOUND;
v_Names(v_counter) := v_FamilyMember;
v_counter := v_counter + 1;
END LOOP;
CLOSE c_Family;
open cursor for
select v_Names from DUAL;
END;why not return the cursor itself, rather than storing it into an array and returning
open c_family for select distinct
case when pr.relationship_cd IN (01,02,04,05) Then 'Child'
when pr.relationship_cd IN (03,09,10) Then 'spouse'
when pr.relationship_cd IN (00,'',null) then 'subscriber'
end as AssesmentResult
from
employee_coverage_level ecl inner join member_benefit_selection mbs
on
ecl.cust_id = mbs.cust_id and ecl.platform_cd = mbs.platform_cd
and ecl.platform_group_nbr = mbs.platform_group_nbr and ecl.ben_id = mbs.ben_id
and ecl.ben_date = mbs.ben_date and ecl.pers_key = mbs.pers_key
inner join person_relationship pr on pr.from_pers_key = mbs.pers_key and pr.pers_key = mbs.mbr_pers_key
where
ecl.pers_key = 343528 and
ecl.cust_id = 1239 and ecl.class_nbr = 211 order by AssesmentResult asc;
return c_family; -
How to type cast PL/SQL table to REF cursor?
any one knows how to CAST PL/SQl table to Ref cursor?
eg
procedure some_name(r_out out sys_refcurosr)
IS
type t is table of tab%ROWTYPE;
my_type t;
begin
select * bulk collect into my_type from tab;
r_out := my_type; -- need help here..
end;
it's 10gref cursor is pointer to result set. You can not cast to PL/SQL table.
1 create or replace procedure some_name(r_out out sys_refcursor)
2 IS
3 begin
4 OPEN r_out for select * from emp;
5* end;
SQL> /
Procedure created.
SQL> var mycursor refcursor;
SQL> exec some_name(:mycursor);
PL/SQL procedure successfully completed.
SQL> set linesize 2000
SQL> print :mycursor;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7369 SMITH CLERK 7902 12/17/80 00:00:00 800 20
7499 ALLEN SALESMAN 7698 02/20/81 00:00:00 1600 300 30
7521 WARD SALESMAN 7698 02/22/81 00:00:00 1250 500 30
7566 JONES MANAGER 7839 04/02/81 00:00:00 2975 20
7654 MARTIN SALESMAN 7698 09/28/81 00:00:00 1250 1400 30
7698 BLAKE MANAGER 7839 05/01/81 00:00:00 2850 30
7782 CLARK MANAGER 7839 06/09/81 00:00:00 2450 10
7788 SCOTT ANALYST 7566 04/19/87 00:00:00 3000 20
7839 KING PRESIDENT 11/17/81 00:00:00 5000 10
7844 TURNER SALESMAN 7698 09/08/81 00:00:00 1500 0 30
7876 ADAMS CLERK 7788 05/23/87 00:00:00 1100 20
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7900 JAMES CLERK 7698 12/03/81 00:00:00 950 30
7902 FORD ANALYST 7566 12/03/81 00:00:00 3000 20
7934 MILLER CLERK 7782 01/23/82 00:00:00 1300 10
14 rows selected. -
CAST: Name of column in a TABLE CAST from a simple table type?
How do I name an anonymous column returned from a table type?
Here is the type:
CREATE OR REPLACE TYPE t_mytab AS TABLE OF VARCHAR2 (10);
Later on, we want to use some of these tables inside a SQL SELECT, so we would have something like this for a variable "tab1" of this type:
CURSOR c1
IS
SELECT t1.*
FROM TABLE (CAST (tab1 AS t_mytab)) t1;
But what is the name of the "column" being returned by this TABLE/CAST?
I've tried doing:
CURSOR c1
IS
SELECT t1.* AS mycol
FROM TABLE (CAST (tab1 AS t_mytab)) t1;
But of course you can't do this when you're selecting *.
I'm sure the solution is blindingly obvious. But I can't see it, so any tips would be welcome.
Thanks.
ChrisHi,
Have you tried:
CURSOR c1
IS
SELECT column_value AS mycol
FROM TABLE (CAST (tab1 AS t_mytab)) t1;
Rod West -
How to Populate a table type variable from a cursor
Hi
I have a stored procedure (P1) that returns a ref cursor as the output.
Another procedure (P2) receives this ref cursor (C).
In this procedure (P2), I want to do a Bulk Collect from this ref cursor (C) in
a table type variable that has been declared locally in the procedure P2. I have created appropriate Object Type and Table Types at the database level.
Please advise how to do it. I tried to do it in different ways, but was not able to do it - each time I faced incompatible data-type related issues.
Regards
MadhupWhat I wrote was unclear. Syntactically it is valid and does something. But consider the advantage of a decent design.
SQL> create or replace procedure p1 (o out sys_refcursor) as
2 begin
3 open o for select * from emp;
4 end p1;
5 /
Procedure created.
SQL> create or replace procedure p2(i sys_refcursor) as
2 type emp_tab is table of emp%rowtype;
3 l_emp_tab emp_tab;
4 begin
5 fetch i bulk collect into l_emp_tab;
6 close i;
7
8 for i in 1..l_emp_tab.count loop
9 NULL;
10 end loop;
11 end p2;
12 /
Procedure created.
SQL> CREATE OR REPLACE PROCEDURE p3 IS
2
3 TYPE myarray IS TABLE OF emp%ROWTYPE;
4 l_data myarray;
5
6 CURSOR r IS
7 SELECT * FROM emp;
8
9 BEGIN
10 OPEN r;
11 LOOP
12 FETCH r BULK COLLECT INTO l_data;
13
14 FOR j IN 1 .. l_data.COUNT
15 LOOP
16 NULL;
17 END LOOP;
18
19 EXIT WHEN r%NOTFOUND;
20 END LOOP;
21 CLOSE r;
22 END p3;
23 /
Procedure created.
SQL> set serverout on
SQL> set timing on
SQL> declare
2 r sys_refcursor;
3 begin
4 FOR i IN 1 .. 10000 LOOP
5 p1(r);
6 p2(r);
7 END LOOP;
8 end;
9 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:01.71
SQL> begin
2 FOR i IN 1 .. 10000 LOOP
3 p3;
4 END LOOP;
5 end;
6 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:01.21
SQL> Again sorry for being less than clear. -
How to pass parameter to cursor for loop having table type?
Hi Friends,
I am wondering how to pass a parameter into second for loop in the example code below.Please see the bold statements and answer my queries.
Thanks a lot .Here is the code .
declare
l_bom_header_tbl BOM_BO_PUB.BOM_HEADER_TBL_TYPE ; ---TABLE TYPE
V_bom_header_tbl Bom_Bo_Pub.Bom_Head_Rec_Type := Bom_Bo_Pub.G_MISS_BOM_HEADER_REC; ---Record type
v_bom_components_tbl Bom_Bo_Pub.Bom_Comps_Tbl_Type := Bom_Bo_Pub.G_MISS_BOM_COMPONENT_TBL;---nested table type
c:=0 number ;
k:=1 number ;
begin
BOMPXINQ.Export_BOM(
P_org_hierarchy_name => l_org_hierarchy_name,
P_assembly_item_name => l_assembly_item_name,
P_organization_code => l_organization_code,
P_alternate_bm_designator => '1Test',
P_Costs => l_costs,
P_Cost_type_id => l_cost_type_id,
X_bom_header_tbl => l_bom_header_tbl,
X_bom_revisions_tbl => l_bom_revisions_tbl,
X_bom_components_tbl => l_bom_components_tbl,
X_bom_ref_designators_tbl => l_bom_ref_designators_tbl,
X_bom_sub_components_tbl => l_bom_sub_components_tbl,
X_bom_comp_ops_tbl => l_bom_comp_ops_tbl,
X_Err_Msg => l_Err_Msg,
X_Error_Code => l_Error_Code);
if l_Error_Code = 0 then
for i in 1 .. l_bom_header_tbl.COUNT LOOP
V_bom_header_tbl.organization_code :='DSC';
Can we assign a table type to record type like below statement?
V_bom_header_tbl.assembly_item_name:= l_bom_header_tbl(i).assembly_item_name ;
k:=1;
I want to pass parameter l_bom_header_tbl(i).assembly_item_name into the for statement below: How to achieve this?
for j in 1 .. l_bom_components_tbl.COUNT LOOP
Can we assign a table type to table type like below statement?
v_bom_components_tbl(k).Assembly_Item_name := l_bom_header_tbl(i).assembly_item_name ;
k := k + 1;
end LOOP;
end loop;
end;
Edited by: ILovePlSql on Mar 22, 2010 7:51 AM
Edited by: ILovePlSql on Mar 22, 2010 8:16 AMILovePlSql wrote:
V_bom_header_tbl.assembly_item_name:= l_bom_header_tbl(i).assembly_item_name ;
v_bom_header_tabl is a record type and l_bom_header_tbl is a table type .So is the above statement ok?I asked you for type definition. Please provide definition of BOM_BO_PUB.BOM_HEADER_TBL_TYPE and Bom_Bo_Pub.Bom_Head_Rec_Type. If BOM_BO_PUB.BOM_HEADER_TBL_TYPE is table of Bom_Bo_Pub.Bom_Head_Rec_Type then your statment is OK. For example:
SQL> declare
2 type BOM_HEADER_TBL_TYPE is table of emp%rowtype index by binary_integer;
3 l_bom_header_tbl BOM_HEADER_TBL_TYPE;
4 V_bom_header_tbl emp%rowtype;
5 begin
6 select * bulk collect into l_bom_header_tbl from emp;
7 for i in 1 .. l_bom_header_tbl.count loop
8 V_bom_header_tbl.ename := l_bom_header_tbl(i).ename;
9 end loop;
10 end;
11 /
PL/SQL procedure successfully completed.
SQL> SY. -
Creating variable of type of a PLSQL table type
I have an object defined as
create or replace type emp_rec as object (col1 date, col2 date);
then I defined
create or replace type data_emp_rec is table of emp_rec;
Now I need to define a variable temp_rec which will host data returned of emp_rec structure.
please advise how to define a variable to have data structure similar to that of emp_rec
declare
temp_rec emp_rec(null, null);
or
temp_rec data_emp_rec;
ThxHello
It's all about casting data types and supplying the right data type to the bulk collect clause:
SQL> SELECT
2 usr.nm,
3 perm.id,
4 perm.descr
5 FROM
6 dt_test_user usr,
7 dt_test_permission perm,
8 dt_test_user_permission usr_perm
9 WHERE
10 usr.id = usr_perm.user_id
11 AND
12 perm.id = usr_perm.permission_id
13 ORDER BY
14 usr.nm
15 /
NM ID DESCR
Barry Bethel 4 Be very enthusiastic about everything
Barry Bethel 2 Advertise slimming products
Dr. Evil 1 Take over the world
Rolf Harris 4 Be very enthusiastic about everything
Rolf Harris 3 Sing very strange songs
SQL> select
2 usr.id,
3 usr.nm,
4 CURSOR(select
5 p.user_id
6 from
7 dt_test_user_permission p
8 where
9 p.user_id = usr.id
10 ) pos_cursor
11 from
12 dt_test_user usr
13 /
ID NM POS_CURSOR
1 Rolf Harris CURSOR STATEMENT : 3
CURSOR STATEMENT : 3
USER_ID
1
1
2 Barry Bethel CURSOR STATEMENT : 3
CURSOR STATEMENT : 3
USER_ID
2
2
3 Dr. Evil CURSOR STATEMENT : 3
CURSOR STATEMENT : 3
USER_ID
3
SQL> select
2 usr.id,
3 usr.nm,
4 CAST(MULTISET( select
5 p.user_id
6 from
7 dt_test_user_permission p
8 where
9 p.user_id = usr.id
10 ) AS permissionList
11 ) pos_ntt
12 from
13 dt_test_user usr
14 /
ID NM POS_NTT(ID)
1 Rolf Harris PERMISSIONLIST(PERMISSION_TYPE(1), PERMISSION_TYPE
(1))
2 Barry Bethel PERMISSIONLIST(PERMISSION_TYPE(2), PERMISSION_TYPE
(2))
3 Dr. Evil PERMISSIONLIST(PERMISSION_TYPE(3))
SQL> declare
2 ul userList;
3 begin
4 select
5 usr.id,
6 usr.nm,
7 CAST(MULTISET( select
8 p.user_id
9 from
10 dt_test_user_permission p
11 where
12 p.user_id = usr.id
13 ) AS permissionList
14 ) pos_ntt
15 bulk collect into
16 ul
17 from dt_test_user
18 usr;
19 end;
20 /
from dt_test_user
ERROR at line 17:
ORA-06550: line 17, column 2:
PL/SQL: ORA-00947: not enough values
ORA-06550: line 4, column 2:
PL/SQL: SQL Statement ignored
SQL> declare
2 ul userList;
3 begin
4 select
5 user_type( usr.id,
6 usr.nm,
7 CAST(MULTISET( select
8 p.user_id
9 from
10 dt_test_user_permission p
11 where
12 p.user_id = usr.id
13 ) AS permissionList
14 )
15 )
16 bulk collect into
17 ul
18 from dt_test_user
19 usr;
20
21 end;
22 /
PL/SQL procedure successfully completed.
SQL> declare
2 ul userList;
3 begin
4 select
5 user_type( usr.id,
6 usr.nm,
7 CAST(MULTISET( select
8 p.user_id
9 from
10 dt_test_user_permission p
11 where
12 p.user_id = usr.id
13 ) AS permissionList
14 )
15 )
16 bulk collect into
17 ul
18 from dt_test_user
19 usr;
20
21 FOR li_Idx IN ul.FIRST..ul.LAST LOOP
22
23 dbms_output.put_line(ul(li_Idx).name);
24
25 FOR li_NttIdx IN ul(li_Idx).permissions.FIRST..ul(li_Idx).permissions.LAST LOOP
26
27 dbms_output.put_line(ul(li_Idx).permissions(li_NttIdx).id);
28
29 END LOOP;
30
31 END LOOP;
32
33 end;
34 /
Rolf Harris
1
1
Barry Bethel
2
2
Dr. Evil
3
PL/SQL procedure successfully completed.HTH
David -
How to return a table to ref cursor?
My client has created a package stored procedure that takes in 2 parameters of VarChar2 and an out parameter which is a table
Following is the package header
CREATE OR REPLACE PACKAGE "PKG_TRAVEL_NEW_SUND" IS
---RECORD TYPE DELARATION
TYPE DIRECT_ALT_REC IS RECORD (SERVICE_NO CBG_DISTANCE_FARE.SERVICE_NO%TYPE,
DISTANCE CBG_DISTANCE_FARE.DISTANCE%TYPE,
CASH_FARE_AC CBG_DISTANCE_FARE.CASH_FARE_AC%TYPE,
CASH_FARE_NON_AC CBG_DISTANCE_FARE.CASH_FARE_NON_AC%TYPE,
CARD_FARE_AC CBG_DISTANCE_FARE.CARD_FARE_AC%TYPE,
CARD_FARE_NON_AC CBG_DISTANCE_FARE.CARD_FARE_NON_AC%TYPE,
EZLINK_FARE_AC CBG_DISTANCE_FARE.EZLINK_FARE_AC%TYPE,
EZLINK_FARE_NON_AC CBG_DISTANCE_FARE.EZLINK_FARE_NON_AC%TYPE,
AVG_RUNTIME CBG_DISTANCE_FARE.AVG_RUNTIME%TYPE,
ALTERNATIVE_NO CBG_DIRECT_ALT.ALTERNATIVE_NO%TYPE,
MAX_FREQ_AM CBG_SVC.MAX_FREQ_AM%TYPE,
MIN_FREQ_AM CBG_SVC.MIN_FREQ_AM%TYPE,
ADVANTAGE_CODE CBG_DIRECT_ALT.ADVANTAGE_CODE%TYPE,
DIST_FARE_CODE_1 CBG_DISTANCE_FARE.DIST_FARE_CODE%TYPE,
DIST_FARE_CODE_2 CBG_DISTANCE_FARE.DIST_FARE_CODE%TYPE,
DIST_FARE_CODE_3 CBG_DISTANCE_FARE.DIST_FARE_CODE%TYPE,
FROM_STOP_CODE CBG_DISTANCE_FARE.FROM_STOP_CODE%TYPE,
TO_STOP_CODE CBG_DISTANCE_FARE.TO_STOP_CODE%TYPE,
MIN_TIME CBG_DIRECT_ALT.MIN_TIME%TYPE,
MIN_FARE CBG_DIRECT_ALT.MIN_FARE%TYPE,
ACT_FARE CBG_DIRECT_ALT.MIN_FARE%TYPE,
TRAVEL_TYPE VARCHAR2(4),
TRANSFER_INFO VARCHAR2(1),
END_TRANSFER_INFO VARCHAR2(1));
--TABLE TYPE DECLARATION
TYPE BUS_INFO_TAB IS TABLE OF DIRECT_ALT_REC INDEX BY BINARY_INTEGER;
-- CURSOR TYPE DECLARATION
TYPE TEMP_REC_STRUCT1 IS RECORD (
RECORD_POSITION BINARY_INTEGER,
DIST_FARE_CODE1 CBG_DISTANCE_FARE.DIST_FARE_CODE%TYPE,
DIST_FARE_CODE2 CBG_DISTANCE_FARE.DIST_FARE_CODE%TYPE,
DIST_FARE_CODE3 CBG_DISTANCE_FARE.DIST_FARE_CODE%TYPE,
ADVANTAGE_CODE CBG_DIRECT_ALT.ADVANTAGE_CODE%TYPE,
MINIMUM_FARE CBG_DIRECT_ALT.MIN_FARE%TYPE,
MINIMUM_TIME CBG_DIRECT_ALT.MIN_TIME%TYPE,
TRAVEL_TYPE VARCHAR2(4) );
TYPE TEMP_TAB_STRUCT1 IS TABLE OF TEMP_REC_STRUCT1 INDEX BY BINARY_INTEGER;
TEMP_TABLE1 BUS_INFO_TAB;
G_RESULTSET_INDEX BINARY_INTEGER := 0 ;
G_TOT_RECS_IN_TAB1 BINARY_INTEGER := 0 ;
TYPE BUS_INFO_CUR IS REF CURSOR RETURN DIRECT_ALT_REC;
---PROCEDURE INSIDE THE PACKAGE
--- PROCEDURE TO SELECT THE RECORDS
PROCEDURE SEL_DIRECT_ALT(P_FROM_STOP_CODE IN VARCHAR2,
P_TO_STOP_CODE IN VARCHAR2,
RESULTSET IN OUT BUS_INFO_TAB);
I'm using ODP.net and here is my code
string storedprocedure = "PKG_TRAVEL_NEW_SUND.SEL_DIRECT_ALT";
//PKG_TRAVEL_NEW_SUND
//CBG003_XP_SP_TEST1
ArrayList retlist = new ArrayList();
OracleConnection curr_conn = this.GetOpenConnection();
OracleCommand cmd = curr_conn.CreateCommand();
cmd = new OracleCommand(storedprocedure, curr_conn);
cmd.CommandType = CommandType.StoredProcedure;
// input parameter
OracleParameter param1 = new OracleParameter();
OracleParameter param2 = new OracleParameter();
param1.ParameterName = "start_code";
param2.ParameterName = "end_code";
param1.OracleDbType = OracleDbType.Varchar2;
param2.OracleDbType = OracleDbType.Varchar2;
param1.Direction = ParameterDirection.Input;
param2.Direction = ParameterDirection.Input;
param1.Size = 5;
param2.Size = 5;
param1.Value = start_codes;
param2.Value = end_codes;
cmd.Parameters.Add(param1);
cmd.Parameters.Add(param2);
OracleParameter outputparam3 = new OracleParameter();
outputparam3.Direction = ParameterDirection.InputOutput;
outputparam3.ParameterName = "output";
outputparam3.OracleDbType = OracleDbType.RefCursor;
// output type
cmd.Parameters.Add(outputparam3);
cmd.ExecuteNonQuery();
At this point, when i execute Query, i get the message telling me that i could have the wrong number or type arguments for the procedure.
I've looked thru countless examples saying i should use a RefCursor, but what else could i miss out?Hi,
This is from Metalink NOTE.219191.1 How to return the values in a PL/SQL table to a ref cursor
Hope it helps,
Greg
This document gives details with an example on how to pass the values
in a PL/SQL table to a ref cursor.
SCOPE & APPLICATION
This document is useful for developers who are familiar with SQL & PL/SQL
How to return the values in a PL/SQL table to a ref cursor
This can be done by using a SQL Object type instead of a PL/SQL table.
Here is an example.
SQL> create or replace type ObjectType as object
2 ( x int,
3 y date,
4 z varchar2(25)
5 );
6 /
Type created.
SQL> create or replace type TabType as table of ObjectType;
2 /
Type created.
SQL> create or replace
2 function demo_function( p_start_row in number,
3 p_end_row in number )
4 return TabType
5 as
6 l_data TabType := TabType();
7 l_cnt number default 0;
8 begin
9 for x in ( select * from emp order by sal desc )
10 loop
11 l_cnt := l_cnt + 1;
12 if ( l_cnt >= p_start_row )
13 then
14 l_data.extend;
15 l_data(l_data.count) :=
16 objectType( x.empno,
17 x.hiredate,
18 x.ename );
19 end if;
20 exit when l_cnt = p_end_row;
21 end loop;
22
23 return l_data;
24 end;
25 /
Function created.
SQL> select *
2 from the ( select cast( demo_function(3,7) as TabType )
3 from dual ) a;
X Y Z
7902 03-DEC-81 FORD
7566 02-APR-81 JONES
7698 01-MAY-81 BLAKE
7782 09-JUN-81 CLARK
7844 08-SEP-81 TURNER
By using a SQL object type, the table can be selected easily.
SQL> create or replace package demo_pkg
2 as
3 type rc is ref cursor;
4
5 procedure p( p_cursor in out rc );
6 end;
7 /
Package created.
SQL> create or replace package body demo_pkg
2 as
3
4 procedure p( P_cursor in out rc )
5 is
6 l_data TabType := TabType();
7 begin
8 for i in 1 .. 3 loop
9 l_data.extend;
10 l_data(i) :=
11 ObjectType( i, sysdate+i, i || ' data');
12 end loop;
13
14 open p_cursor for
15 select *
16 from TABLE ( cast ( l_data as TabType) );
17 end;
18
19 end;
20 /
Package body created.
SQL> set autoprint on
SQL> variable x refcursor
SQL> exec demo_pkg.p(:x)
PL/SQL procedure successfully completed.
X Y Z
1 15-NOV-02 1 data
2 16-NOV-02 2 data
3 17-NOV-02 3 data -
Building an object of nested table types
Hi,
Looking for suggestions for the following.
I have a procedure with 4 table types.
They are in a hierarchical order so that 4 is the child of 3, 3 is the child of 2 and 2 is the child of 1.
One of the columns of table 1 is a table type holding all the child records from table 2,
One of the columns of table 2 is a table type holding all the child records from table 3,
One of the columns of table 3 is a table type holding all the child records from table 4,
I have 4 cursors that pull out all of the data to populate each of my 4 table types.
I am trying to figure out how to nest my fetches to populate all of my table types to create a single object that hold all of my data.
It’s a table of a table of a table of a table.
Column 3 of table 1 holds table 2
Column 3 of table 2 holds table 3
Column 3 of table 3 holds table 4
I’ve tried creating my procedure like this (pseudo code)
declare
tab_1 tab_1_type;
tab_2 tab_2_type;
tab_3 tab_3_type;
tab_4 tab_4_type;
cursor get_tab_1 is
select col1, col2, tab_2 – added the table type for the child records
from data_table_1
cursor get_tab_2(tab_1_pk in number) is
select col1, col2, tab_3 – added the table type for the child records
from data_table_2
where tab_2_fk = tab_1_pk
cursor get_tab_3(tab_2_pk in number) is
select col1, col2, tab_4 – added the table type for the child records
from data_table_3
where tab_3_fk = tab_2_pk
cursor get_tab_4(tab_3_pk in number) is
select col1, col2, col3
from data_table_4
where tab_4_fk = tab_3_pk
begin
open get_tab_1;
loop
open get_tab_2
loop
open get_tab_3
loop
open get_tab_4(tab_3_pk);
bulk collect get_tab_4 into tab_4;
close get_tab_4;
fetch get_tab_3 into tab_3;
tab_4:= null;
exit when get_tab_3 %notfound;
end loop;
close get_tab_3;
fetch get_tab_2 into tab_2;
tab_3:= null;
exit when get_tab_2 %notfound;
end loop;
close get_tab_2;
fetch get_tab_1 into tab_1;
tab_3:= null;
exit when get_tab_1 %notfound;
end loop;
close get_tab_1;
l_return := tab_1;
end;
The above won’t work because once the cursor is opened the child tables will be assigned values of null before they have had a chance to populate from the nested fetches.
It’s almost as if I need to execute the fetch and update the extra columns afterwards somehow, something like:
fetch get_tab_3 into tab_3;
tab_3.col3 := tab_4;
tab_4 := null;
end loop;
close get_tab_3;
can I do that?
Also the above seems very cumbersome. If there is a more elegant way of building up this object I’d like to hear it.
Cheers
YogInteresting little exercise getting a 3 deep nested structure using a single SQL. Below is my attempt. You should be able to run it in any schema that has CREATE TYPE privs.
SQL> -- Nested structure design:
SQL> --
SQL> -- USER LIST = (
SQL> -- (USER1,OBJECT_LIST1).., (USERn,OBJECT_LISTn)
SQL> -- )
SQL> --
SQL> -- LIST OF OBJECTS = (
SQL> -- (TYPE1, NAME_LIST1).., (TYPEn, NAME_LISTn)
SQL> -- )
SQL> --
SQL> -- LIST OF NAMES = ( NAME1..,NAMEn )
SQL>
SQL>
SQL> create or replace type TObjectList is table of varchar2(50)
2 /
Type created.
SQL>
SQL> create or replace type TObjType is object(
2 obj_type varchar2(50),
3 obj_list TObjectList
4 );
5 /
Type created.
SQL>
SQL> create or replace type TObjTypeList is table of TObjType;
2 /
Type created.
SQL>
SQL> create or replace type TUser is object(
2 user_name varchar2(50),
3 objects TObjTypeList
4 );
5 /
Type created.
SQL>
SQL> create or replace type TUserList is table of TUser;
2 /
Type created.
SQL>
SQL> col NESTED_STRUCTURE format a100
SQL>
SQL> -- constructing the above user list (have made the start of the USER bold in the output below)
SQL> select
2 CAST( COLLECT(
3 TUser(
4 username,
5 CAST( MULTISET(
6 select
7 TObjType(
8 object_type,
9 CAST( COLLECT(o.object_name) as TObjectList)
10 )
11 from all_objects o
12 where o.owner = u.username
13 group by
14 o.object_type
15 ) as TObjTypeList
16 )
17 )
18 ) as TUserList
19 ) as NESTED_STRUCTURE
20 from all_users u
21 where u.username in ('BILLY','DBSNMP')
22 /
NESTED_STRUCTURE(USER_NAME, OBJECTS(OBJ_TYPE, OBJ_LIST))
TUSERLIST(TUSER('BILLY', TOBJTYPELIST(TOBJTYPE('FUNCTION', TOBJECTLIST('GETEMP', 'GETEMP2', 'TESTRET
URN', 'WTF', 'ANOOP_REF')), TOBJTYPE('INDEX', TOBJECTLIST('PK_DEPT', 'PK_EMP')), TOBJTYPE('PROCEDURE
', TOBJECTLIST('USESEQ1', 'FOOPROC', 'W')), TOBJTYPE('TABLE', TOBJECTLIST('X', 'LOAD_TABLE', 'DEPT',
'EMP', 'BONUS', 'SALGRADE')), TOBJTYPE('TYPE', TOBJECTLIST('TEMP', 'TEMPLOYEE', 'TX', 'TARRAY2D', '
TARRAY1D', 'TARRAY3D', 'TOBJECT', 'TOBJTYPE', 'TOBJECTLIST', 'TOBJTYPELIST', 'TUSER', 'TUSERLIST', '
SYSTPTkQoC5hBR+DgQPsKOl0PFQ==', 'SYSTPTkQoC5hyR+DgQPsKOl0PFQ==', 'SYSTPTkQoC5qzR+DgQPsKOl0PFQ==', 'S
YSTPTkQoC5raR+DgQPsKOl0PFQ==')))), TUSER('DBSNMP', TOBJTYPELIST(TOBJTYPE('INDEX', TOBJECTLIST('MGMT_
DB_FILE_GTT_PK', 'MGMT_DB_SIZE_GTT_PK')), TOBJTYPE('PACKAGE', TOBJECTLIST('MGMT_RESPONSE')), TOBJTYP
E('PACKAGE BODY', TOBJECTLIST('MGMT_RESPONSE')), TOBJTYPE('SEQUENCE', TOBJECTLIST('MGMT_RESPONSE_CAP
TURE_ID', 'MGMT_RESPONSE_SNAPSHOT_ID')), TOBJTYPE('TABLE', TOBJECTLIST('MGMT_SNAPSHOT', 'MGMT_SNAPSH
OT_SQL', 'MGMT_BASELINE', 'MGMT_BASELINE_SQL', 'MGMT_CAPTURE', 'MGMT_CAPTURE_SQL', 'MGMT_RESPONSE_CO
NFIG', 'MGMT_LATEST', 'MGMT_LATEST_SQL', 'MGMT_HISTORY', 'MGMT_HISTORY_SQL', 'MGMT_TEMPT_SQL', 'MGMT
DBFILE_GTT', 'MGMT_DB_SIZE_GTT')), TOBJTYPE('VIEW', TOBJECTLIST('MGMT_RESPONSE_BASELINE')))))
SQL>
PS. To understand how the SQL works, run it from the inside out - i.e. run the innermost select on its own to see the output and then add to it until the full select is reached. -
Error while doing Bulk Collect to a table type
I'm using a Table type to accumulate resultset from a loop and finally return the records in the table type as a ref cursor to the front end.
But when I'm using Bult collect to insert into the table type object it keeps throwing an error
'PLS-00597: expression 'TAB_CALENDAR_AVAIL_RESULTSET' in the INTO list is of wrong type'. Can someone help me to let me know what could be the reason for this error. I'm not able to proceed further, please help.
Here is the code.
CREATE OR REPLACE PACKAGE hotel
AS
TYPE calendar_cursor IS REF CURSOR;
TYPE type_calendar_avail is RECORD(
HOTEL_ID AVAILABILITY_CALENDAR.hotel_id%TYPE,--varchar2(4), --AVAILABILITY_CALENDAR.hotel_id%TYPE,
AVAIL_DATE AVAILABILITY_CALENDAR.AVAIL_DATE%TYPE ,
TOTAL_COUNT number
TYPE type_calendar_avail_resultset IS TABLE OF type_calendar_avail;
tab_calendar_avail_resultset type_calendar_avail_resultset ; -- declare variable of type type_calendar_avail_resultset
PROCEDURE sp_get_calendar_results (
sallhotelswithavaildate VARCHAR2,
ilengthofstay NUMBER,
sorcowner VARCHAR2,
all_unittypes VARCHAR2, --DBMS_SQL.VARCHAR2S
calendar_resultset OUT calendar_cursor
-- tab_calendar_avail_resultset out type_calendar_avail_resultset
PROCEDURE sp_get_calendar_results (
sallhotelswithavaildate VARCHAR2,
ilengthofstay NUMBER,
-- ivariant NUMBER,
sorcowner VARCHAR2,
all_unittypes VARCHAR2, --DBMS_SQL.VARCHAR2S
calendar_resultset OUT calendar_cursor
AS
sbuf VARCHAR2 (200);
sepr VARCHAR2 (1);
shotelwithdate VARCHAR2 (200);
shotelid VARCHAR2 (10);
savaildate VARCHAR2 (8);
sactualavaildate VARCHAR2 (8);
pos NUMBER;
istart NUMBER;
sstartdate VARCHAR2 (8);
senddate VARCHAR2 (8);
squery VARCHAR2 (32767) := '';
sunittypecond VARCHAR2 (500) := '';
sunitdesccond VARCHAR2 (500) := '';
v_unit_cond a_unit_cond;
tempunitcond VARCHAR2 (50) := '';
BEGIN
istart := 1;
LOOP
tempunitcond := hotel.stringtokenizer (all_unittypes, istart, '|');
IF tempunitcond IS NOT NULL
THEN
v_unit_cond (istart) := tempunitcond;
istart := istart + 1;
END IF;
EXIT WHEN tempunitcond IS NULL;
END LOOP;
sunitdesccond := hotel.get_unit_description_cond (v_unit_cond);
DBMS_OUTPUT.put_line ('unit description : ' || sunitdesccond);
sbuf := sallhotelswithavaildate;
sepr := '|';
istart := 1;
LOOP
shotelwithdate := hotel.stringtokenizer (sbuf, istart, sepr);
EXIT WHEN shotelwithdate IS NULL;
shotelid :=
SUBSTR (shotelwithdate, 1, INSTR (shotelwithdate, ',') - 1);
savaildate :=
SUBSTR (shotelwithdate, INSTR (shotelwithdate, ',') + 1);
squery :=
' SELECT MIN (ad.avail_date) '
|| ' FROM wvo_fonres.fpavail_daily ad'
|| ' WHERE ad.hotel_id = '
|| shotelid
|| ' AND ad.days_left >= '
|| ilengthofstay
|| ' AND ad.avail_date >= '
|| savaildate;
IF UPPER (sorcowner) = 'N'
THEN
squery :=
squery
|| ' AND ad.ORC_TYPE != ''R'' and ad.ORC_TYPE != ''P'' and ad.ORC_TYPE != ''E'' ';
END IF;
squery := squery || ' AND ( ' || sunitdesccond || ') ';
EXECUTE IMMEDIATE squery
INTO sactualavaildate;
DBMS_OUTPUT.put_line ('Actual available Date: ' || sactualavaildate);
hotel.sp_get_startdate_enddate (sactualavaildate,
--ivariant,
sstartdate,
senddate
sunittypecond := hotel.get_unittype_cond (v_unit_cond, sorcowner);
-- execute immediate
squery :=
'select HOTEL_ID, AVAIL_DATE, ' || sunittypecond || ' AS TOTAL_COUNT '
|| ' FROM AVAILABILITY_CALENDAR A '
|| 'WHERE '
|| 'AVAIL_DATE >= '''
|| sstartdate
|| ''' '
|| 'AND '
|| 'AVAIL_DATE <= '''
|| senddate
|| ''' '
||'AND '
|| 'A.HOTEL_ID IN ('
|| shotelid
|| ') '
|| 'AND ('
|| sunittypecond
|| '> 0) '
|| -- where total available count of unit type is greater than 0
' ORDER BY AVAIL_DATE'; --order clause
open calendar_resultset for squery;
fetch calendar_resultset BULK COLLECT INTO tab_calendar_avail_resultset;
istart := istart + 1;
END LOOP;
COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
NULL;
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line
(SQLERRM (SQLCODE));
RAISE;
END sp_get_calendar_results;
END hotel;
/1. put tags [co[/b][b]de] and [co[/b][b]de] around your code, so it's readable
B. what does "hotel.get_unittype_cond (v_unit_cond, sorcowner)" actually retun?
and third, try this for the array declaration:
tab_calendar_avail_resultset type_calendar_avail_resultset := type_calendar_avail_resultset ; () ; -
Block with more than one table type agurment - Update Procedure for Block
Hi,
I have one form with 3 Block. First Block is single row block, and other 2 are details block . The details balocks are based on the Procedure datasource, because of the complex query conditions. Now my requirement is When Inserting / Updating the Master Block (Single Row Block), I need to get the values in the two details block , because I need to update some other tables also based on these values. I created a procedure with two Table Type parameters (for each details block) , but when I using this procedure as the Update Procedure Name in the block, I am getting the error Only One table type arguement is allowed. Is there any other method to implement this.
Thanks in advance.Rizly,
A quick summary to make sure I understand your requirements. You have a single row base table master block with two detail blocks that are based on Procedures. When you update the single row base table master block, you need all of the data in the two procedure based detail blocks as there are updates that you have to perform to other tables that use this data. You have created a stored procedure that take two PL/SQL tables as parameters, but you are getting the error that only 1 table parameter is allowed.
I need to ask you a few questions first. What is your Forms version? The stored procedure you created; are you using this procedure in the "On-Insert, On-Update, On-Delete" triggers or do you call the procedure in one of the Base Table block ("Key-Commit, When-Button-Pressed" or other trigger)? When you modify or add a new Master block record are you adding values to the detail blocks or using values from the previous Master block record?
If you are using your procedure in the On-Insert, On-Update or On-Delete trigger(s), then based on your description, the error you are receiving is correct. The "On-..." triggers are constrained in that their procedures expect only a single PL/SQL table, Table of Records or Ref Cursor as a parameter. This is a Forms constraint - not a PL/SQL constraint as Forms is expecting you to only perform actions on the block where the "On-..." Trigger is located.
Perhaps you should consider creating a database Package that has two package specification constructs (Ref Cursor, Table of Records, etc) you can populate from Forms and then simply call the package procedure that will use the Ref Cursors to perform the needed update or inserts.
Hope this helps.
Craig...
If mine or someone elses response was helpful, please mark it accordingly -
What is the maximum rows allowed in PLSQL array table type?
Hi,
I have a procedure and it contains the cursor which will fetch more than 500 records. And i have 5 output parameters to store the values coming from the cursor. I don't want to store that into custom table. I want to save it one table type array or something like that. Now i want to know what is the maximum storage of array table type? If i store more than 500 data, how will be the performance? Then is there any other way to achieve this? And that should not decrease the preformace.Let me know your thoughts.
ThanksIt really depends on what you are planning to do with the records once you return them from your stored procedure, and what client is on the receiving end of the results.
One option would be to just return a ref cursor and let the client deal with retreiving the rows themselves, whether one by on or by a bulk collect. Another option would be to declare a table of records matching the result set and do a bulk collect into that table type in your procedure and return the table type to the caller. You could also declare a table type for each field in the resultset, bulk collect the records into thos types and return one for each field.
Personally, I would likely go with returning a ref cursor. Both of the collect the resultset in your procedure and then return collections to the caller methods require memory on the database server to hold the entire resultset and memeory on the client to hold the entire resultset. While 500 records is probably not going to be too bad on memory, if the result set grows, you will run into memory issues at some point.
John -
Information on table type datatypes.
Hi,
I am working with the table type composite datatype. After I insert the values to the table type declared variable how will I be able to print that or use it in further DML operations.
example
create or replace procedure xxx_proc as
type u_rec is record
empno number(5),
ename varchar2(10));
type m_tbl is table of u_rec index by binary_integer;
cursor c1 is select empno, ename from scott.emp;
nokia m_tbl;
motorola u_rec;
i number:=0;
begin
for j in c1 loop
fetch c1 into motorola;
i := i+1;
nokia(i) := motorola;
end loop;
dbms_output.put_line(nokia.first);
dbms_output.put_line(nokia.last);
dbms_output.put_line(nokia(2));
end;
I execute this proecedure it returns error at 19, how will I print the values.
Regards
Jhansi.You are driving me crazy
y.empno(i) := i;This should be...
y(i).empno := i;
SQL> declare
2 type xx is table of emp%rowtype index by binary_integer;
3 y xx;
4 i number :=0;
5 begin
6 for j in 1..20 loop
7 i := i+j;
8 y(i).empno := i;
9 y(i).ename := 'Mark';
10 y(i).job := 'Clerk';
11 y(i).mgr := i+5;
12 y(i).hiredate := sysdate;
13 y(i).sal := i* 100;
14 y(i).comm := i*10;
15 y(i).deptno := 10;
16 end loop;
17
18 dbms_output.put_line('20 records inserted successfully');
19 end;
20 /
20 records inserted successfully
PL/SQL procedure successfully completed.It works but i have no clue what in the world are you trying to do ;)
Edited by: Karthick_Arp on Feb 18, 2009 9:19 PM -
Mapping of PLSQL table type Date to java
i am having problem in mapping plsql table type DATE in java,
able to execute procedures which return plsql table type NUMBER,VARCHAR.
i am using oracle 9 , jdk1.4, oci driver, windows 2000.
sample code:
registering:
st.registerIndexTableOutParameter(15,100,OracleTypes.DATE,1000);
st.registerIndexTableOutParameter(16,100,OracleTypes.DATE,1000);
st.execute();
getting out params in arrays:
java.sql.Date[] O_lSubFolder_CrOn=(java.sql.Date[])java.sql.Date[] st.getPlsqlIndexTable(15);
O_lSubFolder_MdOn=(java.sql.Date[])st.getPlsqlIndexTable(16);
error while executing the code:
java.sql.SQLException: Invalid PL/SQL Index Table element type
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:180)
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:222)
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:285)
at oracle.jdbc.driver.OraclePreparedStatement.checkPlsqlIndexTableBindTypes(OraclePreparedSt
atement.java:2705)
at oracle.jdbc.driver.OracleCallableStatement.registerIndexTableOutParameter(OracleCallableS
tatement.java:834)
can anyone help me to solve this problem.i am having problem in mapping plsql table type
DATE in java,
able to execute procedures which return plsql table
type NUMBER,VARCHAR.
i am using oracle 9 , jdk1.4, oci driver, windows
2000.
sample code:
registering:
st.registerIndexTableOutParameter(15,100,OracleTypes.D
TE,1000);
st.registerIndexTableOutParameter(16,100,OracleTypes.D
TE,1000);
st.execute();
getting out params in arrays:
java.sql.Date[]
O_lSubFolder_CrOn=(java.sql.Date[])java.sql.Date[]
st.getPlsqlIndexTable(15);
O_lSubFolder_MdOn=(java.sql.Date[])st.getPlsqlIndexTab
e(16);
can anyone help me to solve this problem.1. Write a wrapper procedure that converts the table of dates to either number or date and then re-convert the table back into date.
2. Since it's an out param you could create a temp table, insert the contents of the index by array into it and return a cursor.
3. Create a oracle type using CREATE TYPE and then use an array of the type.
David Rolfe
Orinda Software -
Calling Oracle Stored proc with record type and table Type
I have a oracle SP which takes record type and table Type which are used for order management.
Is there anay way to populate parameters with these datatypes and call the stored procedure using ODP.NET?
Please help.
Thanks in advanceHi,
ODP supports associative arrays and REF Cursors. There is no support for PLSQL table of records.
Jenny
Maybe you are looking for
-
Not able to Delete the data from Memory card
Hi all, I have bought a new nokia 3120 classic.it is working fine but recently i have received some data from my friend. Then suddenly the problem begins like.. when i take a photo.. i am getting error like the image is not in the format and i am not
-
Can give another developer access to my MUSE documents?
Hi, I made several products in MUSE lately as a kind of prototyping for testing and descionmaking at a publishing house in Norway. Now the website design has to be mapped to a publishing system for a product line. Ofcourse I can make the HTML export
-
Office 2013 deployment customisation
Hello, just added O2013 to applications. Used OCT, placed msp to Updates. Run litetouch from test VM. Installation run silently. 100% success. Here are the points that I would like to adjust: 1. When first started Word. I got the Windows with update
-
Alv..handling at new event in ALV
Hi, I have a problem in ALV. In the report I have to sum up the cols displaying Sales Order and the col displaying P.O #. However while summing for the same sales order there is a one to one correspondence with the P.O eg . SO # PO # 3301
-
Hi i'm new to flex.I want to use caching in the flex application but i couldnt find any details regrading that.In my application will be getting values from a xml feed but on holidays there wont be any change in the values so instead of ping the serv