Cast multiset
How does cast multiset work, I have a huge sql whcih is returning one value say p_opp_id ( on the basis of this i need few more coumns) , i was suggested to use cast multiset , what is cast multiset and how it works
CAST(MULTISET(subquery) AS collection_type) converts the result of a subquery into a collection.
An example I had lying around:
CREATE TABLE master (table_name PRIMARY KEY) AS
SELECT table_name
FROM user_tables;
CREATE TABLE detail AS
SELECT table_name, column_name, data_type
FROM user_tab_columns;
CREATE OR REPLACE TYPE name_strvalue_ot AS OBJECT
( name VARCHAR2(30)
, value VARCHAR2(50) );
CREATE OR REPLACE TYPE name_strvalue_tt AS TABLE OF name_strvalue_ot;
SELECT m.table_name
, CAST(
MULTISET
( SELECT name_strvalue_ot(d.column_name, d.data_type)
FROM detail d
WHERE d.table_name = m.table_name
) AS name_strvalue_tt) cols
FROM master m;
BEGIN
FOR r IN
SELECT m.table_name
, CAST(
MULTISET
( SELECT name_strvalue_ot(d.column_name, d.data_type)
FROM detail d
WHERE d.table_name = m.table_name
) AS name_strvalue_tt) cols
FROM master m
LOOP
DBMS_OUTPUT.PUT_LINE(r.table_name || ': ' || r.cols.count || ' columns');
END LOOP;
END;
/
Similar Messages
-
Error in cast multiset in collections
DECLARE
TYPE emp_dept_rec IS RECORD (
v_sal emp.sal%TYPE,
v_name emp.ename%TYPE,
v_deptname dept.DEPTNAME%type
TYPE emp_dept_tab_type IS TABLE OF emp_dept_rec;
l_emp_dept_tab emp_dept_tab_type;
type emp_tab is table of emp%rowtype;
type l_emp_tab is table of emp%rowtype;
type dept_tab is table of dept%rowtype;
type l_dept_tab is table of dept%rowtype;
cursor e1 is
select * from emp;
cursor d1 is select * from dept;
begin
OPEN e1;
FETCH e1
BULK COLLECT INTO l_emp_tab;
open d1;
FETCH d1
BULK COLLECT INTO l_dept_tab;
select cast(multiset (select em.sal,em,ename ,dep.DEPTNAME
from table(l_emp_tab) em,table(l_dept_tab) dep
where em.deptno=dep.deptno)
as emp_dept_tab_type)
into l_emp_dept_tab ;
end;
it is giving error as
ORA-06550: line 43, column 25:
PL/SQL: ORA-00923: FROM keyword not found where expected
ORA-06550: line 39, column 5:
PL/SQL: SQL Statement ignoredHere is an example.
SQL> CREATE OR REPLACE TYPE emp_rec IS OBJECT (
2 v_sal NUMBER(7,2),
3 v_name VARCHAR2(35),
4 v_empno NUMBER(4),
5 v_deptno NUMBER(2)
6 )
7 ;
8 /
Type created.
SQL> CREATE OR REPLACE TYPE emp_tab IS TABLE OF emp_rec;
2 /
Type created.
SQL> CREATE OR REPLACE TYPE dept_rec IS OBJECT (
2 v_deptno NUMBER,
3 v_dname VARCHAR2(50)
4 )
5 ;
6 /
Type created.
SQL> CREATE OR REPLACE TYPE dept_tab IS TABLE OF dept_rec;
2 /
Type created.
SQL> CREATE OR REPLACE TYPE emp_dept_rec IS
2 OBJECT (
3 v_sal NUMBER,
4 v_name VARCHAR2(35),
5 v_deptname VARCHAR2(30)
6 );
7 /
Type created.
SQL> CREATE OR REPLACE TYPE emp_dept_tab_type IS TABLE OF emp_dept_rec;
2 /
Type created.
SQL> set serverout on
SQL> DECLARE
2 l_emp_dept_tab emp_dept_tab_type; --emp_dept_tab_type declared in database
3 l_emp_tab emp_tab; --emp_tab declared in database
4 l_dept_tab dept_tab; --dept_tab declared in database
5
6 CURSOR e1 IS
7 SELECT emp_rec(sal, ename, empno, deptno) FROM emp; --Note the type casting here
8
9 CURSOR d1 IS
10 SELECT dept_rec(deptno, dname) FROM dept; --Note the type casting here
11 BEGIN
12 OPEN e1;
13
14 FETCH e1 BULK COLLECT
15 INTO l_emp_tab;
16
17 OPEN d1;
18
19 FETCH d1 BULK COLLECT
20 INTO l_dept_tab;
21
22 SELECT CAST(MULTISET (SELECT em.v_sal, em.v_name, dep.v_dname
23 FROM TABLE(l_emp_tab) em, TABLE(l_dept_tab) dep
24 WHERE em.v_deptno = dep.v_deptno) AS emp_dept_tab_type)
25 INTO l_emp_dept_tab
26 FROM DUAL;
27 FOR i IN 1 .. l_emp_dept_tab.COUNT LOOP
28 dbms_output.put_line(l_emp_dept_tab(i)
29 .v_sal || '--' || l_emp_dept_tab(i)
30 .v_name || '--' || l_emp_dept_tab(i).v_deptname);
31 END LOOP;
32
33 END;
34 /
1300--MILLER--ACCOUNTING
5000--KING--ACCOUNTING
2450--CLARK--ACCOUNTING
3000--FORD--RESEARCH
1100--ADAMS--RESEARCH
3000--SCOTT--RESEARCH
2975--JONES--RESEARCH
800--SMITH--RESEARCH
950--JAMES--SALES
1500--TURNER--SALES
2850--BLAKE--SALES
1250--MARTIN--SALES
1250--WARD--SALES
1600--ALLEN--SALES
PL/SQL procedure successfully completed.It is just for educational purpose, because the thing you have achieved by so much programming can be done easily by simple join in the table itself.
user10447332 Newbie
Handle: user10447332
Status Level: Newbie
Registered: Oct 20, 2008
Total Posts: 227
Total Questions: 153 (152 unresolved) >
What a record! and most of the time you don't care to follow/revisit the thread also!. -
I have the following sql
SELECT *
FROM (SELECT updatedby, updateddate, ROWNUM,
ent_id
FROM (SELECT hstbe.updatedby,
hstbe.updateddate,
TO_CHAR
(hstbe.entry_id
) ent_id
FROM hst_rb_booking_entry hstbe
--WHERE hstbe.entry_id = entryid
UNION
SELECT hstli.updatedby,
hstli.updateddate,
hstli.entry_id ent_id
FROM hst_rb_line_item hstli)
-- WHERE hstli.entry_id = be.booking_entry_id)
ORDER BY updateddate)
WHERE ROWNUM < 6)
I am unable to put it in cat multiset as have to retrieve these as collection in my sql of ref cursor. please help me in putting it in cast multiset.Thenks for the reply.
I have allready encounter this page in the past.
I tryed to use "JIMI" wich is a good tool but I haven't found a function to control image resolution in it's documentation.
If you do know how to control dpi threw "JIMI" please tell me. -
Using where clause with cast multiset
version
oracle 10g
how to select values based on values in the object.
CREATE OR REPLACE TYPE init_queue AS OBJECT (
seq_num_q NUMBER,
source_system_name VARCHAR2 (50 BYTE),
milestone_id NUMBER,
milestone_date DATE,
downstream_order_number VARCHAR2 (175 BYTE),
leg_id VARCHAR2 (175 BYTE),
statuspro_captured_date DATE,
pon VARCHAR2 (26 BYTE),
milestone_source VARCHAR2 (26 BYTE),
session_id NUMBER,
reconfirmation_flag CHAR (1 BYTE),
vec_flag CHAR (1 BYTE)
CREATE OR REPLACE TYPE tab_init_queue AS TABLE OF init_queue;
SET serveroutput on;
DECLARE
v_list tab_init_queue := tab_init_queue ();
v_arr_sort tab_init_queue := tab_init_queue ();
BEGIN
SELECT init_queue (seq_num_q,
source_system_name,
milestone_id,
milestone_date,
downstream_order_number,
leg_id,
statuspro_captured_date,
pon,
milestone_source,
session_id,
reconfirmation_flag,
vec_flag
BULK COLLECT INTO v_list
FROM r_cust_status_init_queue;
SELECT CAST (MULTISET (SELECT *
FROM TABLE (v_list)
WHERE v_list.milestone_id = 11 -- * How to select values based on milestone.*
) AS tab_init_queue)
INTO v_arr_sort
FROM DUAL;
DBMS_OUTPUT.put_line (v_arr_sort.COUNT);
END;
/Edited by: new learner on Aug 23, 2010 7:35 PMnew learner wrote:
version
oracle 10g
how to select values based on values in the object.
CREATE OR REPLACE TYPE init_queue AS OBJECT (
seq_num_q NUMBER,
source_system_name VARCHAR2 (50 BYTE),
milestone_id NUMBER,
milestone_date DATE,
downstream_order_number VARCHAR2 (175 BYTE),
leg_id VARCHAR2 (175 BYTE),
statuspro_captured_date DATE,
pon VARCHAR2 (26 BYTE),
milestone_source VARCHAR2 (26 BYTE),
session_id NUMBER,
reconfirmation_flag CHAR (1 BYTE),
vec_flag CHAR (1 BYTE)
CREATE OR REPLACE TYPE tab_init_queue AS TABLE OF init_queue;
SET serveroutput on;
DECLARE
v_list tab_init_queue := tab_init_queue ();
v_arr_sort tab_init_queue := tab_init_queue ();
BEGIN
SELECT init_queue (seq_num_q,
source_system_name,
milestone_id,
milestone_date,
downstream_order_number,
leg_id,
statuspro_captured_date,
pon,
milestone_source,
session_id,
reconfirmation_flag,
vec_flag
BULK COLLECT INTO v_list
FROM r_cust_status_init_queue;
SELECT CAST (MULTISET (SELECT *
FROM TABLE (v_list)
WHERE v_list.milestone_id = 11 -- * How to select values based on milestone.*
) AS tab_init_queue)
INTO v_arr_sort
FROM DUAL;
DBMS_OUTPUT.put_line (v_arr_sort.COUNT);
END;
/Edited by: new learner on Aug 23, 2010 7:35 PMLike this.
DECLARE
v_list tab_init_queue := tab_init_queue ();
v_arr_sort tab_init_queue := tab_init_queue ();
BEGIN
v_list.extend;
v_list(v_list.count) := init_queue(1, '1', 11, sysdate, '1', '1', sysdate, '1', '1', 1, '1', '1');
8
SELECT CAST (MULTISET (SELECT *
FROM TABLE (v_list)
WHERE milestone_id = 11 -- * How to select values based on milestone.*
) AS tab_init_queue)
INTO v_arr_sort
FROM DUAL;
DBMS_OUTPUT.put_line (v_arr_sort.COUNT);
END;
1
PL/SQL procedure successfully completed.
ME_XE?ME_XE?
ME_XE?select * from v$version;
BANNER
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
5 rows selected.
ME_XE?It would have been easier if you'd made a simple example so i didn't have to type out the example record (since your original code referenced a table you didn't provide DDL and INSERTS for).
Something to keep in mind for the future (the easier you make it for us, the more likely we are to help). -
How to get result without single cotes in ''Cast(Multiset( '' Result.
select cast(multiset(select column_name
from user_tab_columns
where table_name = 'DAILY_PRODN_MIS'
and column_name like '%STOCK%'
order by column_name) as tab_type) result from dual;
RESULT
TAB_TYPE('BAGS_STOCK', 'BLUE_DUST_STOCK', 'CEMENT_STOCK', 'CEMENT_STOCK_33', 'CEMENT_STOCK_43', 'CEMENT_STOCK_53', 'CK_ADJ', 'COAL_IND_D_STOCK', 'COAL_IND_D_STOCK_ADJ', 'COAL_IND_E_STOCK', 'COAL_IND_E_STOCK_ADJ', 'COAL_IND_F_STOCK','OCK_ADJ', 'MTD_COAL_IMP_D_STOCK_ADJ', 'MTD_COAL_IMP_E_STOCK_ADJ', 'MTD_COAL_IND_A_STOCK_ADJ', 'MTD_COAL_IND_B_STOCK_', 'YTD_COAL_IMP_B_STOCK_ADJ', 'YTD_COAL_IMP_C_STOCK_ADJ', 'YTD_COAL_IMP_D_STOCK_ADJ', 'YTD_COAL_IMP_E_STOCK_ADJ')
How can i get result without single cotes for each column.Your query currently returns a collection type (tab_type) whereas it appears you want to return a delimited string.
There are actually quite a few ways to achieve this - with your own function, with a user-defined aggregate functions (e.g. Tom Kyte's stragg), with the MODEL clause or with CONNECT BY, e.g.
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
SQL> SELECT table_name,
2 SUBSTR (MAX (SYS_CONNECT_BY_PATH (
3 column_name, ',')), 2) column_names
4 FROM (SELECT table_name, column_name,
5 ROW_NUMBER () OVER (
6 PARTITION BY table_name
7 ORDER BY column_id) column_order
8 FROM user_tab_columns
9 WHERE table_name = 'BANK_ACCOUNT'
10 AND column_name LIKE '%U%') utc
11 START WITH column_order = 1
12 CONNECT BY column_order = PRIOR column_order + 1
13 AND table_name = PRIOR table_name
14 GROUP BY table_name;
TABLE_NAME COLUMN_NAMES
BANK_ACCOUNT ACCOUNT_NAME,ACCOUNT_NUMBER
SQL> -
CAST MULTISET using a recursive UDT using REF
I am trying to create a recursive object and populate it using cast and multiset. However I keep getting the following error:
ORA-00932: inconsistent datatypes: expected UDT got CHAR
00932. 00000 - "inconsistent datatypes: expected %s got %s"
*Cause:
*Action:
Error at Line: 96 Column: 47
I have been looking on OTN, Google ... every where I can think of. I am missing somthing simple or it is not possible I have not found documentation either way. Found one reference which was close to what I am doing. However the link to the explanation was broken ( Oracle Forums link ).
I have created a simple example below.
PS. Please no comment on using system ( i know :) ) this is a scratch database.
16:53:49 SQL> CREATE OR REPLACE TYPE system.MY_TYPE;
16:54:02 2 /
Type created.
16:54:04 SQL> CREATE OR REPLACE TYPE system.MY_TYPE_LIST AS TABLE OF REF system.MY_TYPE;
16:54:11 2 /
Type created.
16:54:13 SQL> CREATE OR REPLACE TYPE system.MY_TYPE AS OBJECT
16:54:27 2 ( COLUMN1 VARCHAR2(30),
16:54:35 3 SUB_LIST system.MY_TYPE_LIST
16:54:45 4 );
16:54:52 5 /
Type created.
16:54:55 SQL>
16:54:55 SQL> select system.my_type( tc.column_name, null ) from dba_tab_columns tc where tc.owner='SYS' and tc.table_name='DBA_TABLES';
--Should be noted there are no errors occured here* 16:56:00 SQL>
16:57:57 SQL> select system.my_type(
16:59:14 2 v.view_name,
16:59:20 3 cast( multiset (
16:59:26 4 select
16:59:31 5 tc.column_name,
16:59:36 6 null
16:59:45 7 from dba_tab_columns tc
16:59:51 8 where tc.table_name=v.view_name
16:59:56 9 and tc.owner=v.owner ) as system.my_type_list ) )
17:00:01 10 from dba_views v
17:00:06 11 where v.view_name = 'DBA_TABLES';
tc.column_name,
ERROR at line 5:
ORA-00932: inconsistent datatypes: expected UDT got CHAR
17:00:14 SQL>create or replace type t_lookuprec as object
(Select columns1,2,3,....100
FROM A, B, C, D, E
WHERE ROWNUM < 1);You are correct that you need to use CREATE TYPE to use the type in SQL.
However unless I am mistaken you appear to have invented your own syntax for CREATE TYPE, suggest you refer to Oracle documentation. -
Question on using CAST, MULTISET and TABLE
Hi,
I am trying to do something that is utterly meaningless, but I am studying the use of CAST with MULTISET and TABLE.
I have created a type: a Nested Table of Number values:
create type numTable as table of number;
Now I perform the following query:
select d.dname
, ( select avg(column_value)
from table
( cast( d.salaries as numTable)
) Department_Avg_Salary
from ( select cast
( multiset
( select e.sal
from emp e
where e.deptno = d1.deptno
) as numTable
) salaries
, d1.dname
from dept d1
) d
I had expected to see each department name and the average salary within that department. Instead, I see the same Department_Avg_Salary value for each row - the average of the first department:
DNAME DEPARTMENT_AVG_SALARY
ACCOUNTING 1875
RESEARCH 1875
SALES 1875
OPERATIONS 1875
However, when I change the query to the following:
select d.dname
, d.salaries
from ( select cast
( multiset
( select e.sal
from emp e
where e.deptno = d1.deptno
) as numTable
) salaries
, d1.dname
from dept d1
) d
I get the following result - note that each department shows the correct list of salaries, not the list of the 1st department's salaries over and over.
DNAME
SALARIES
---------------------------------------------------------ACCOUNTING
NUMTABLE(2450, 1300)
RESEARCH
NUMTABLE(800, 2975, 3000, 5000, 1100, 3000)
SALES
NUMTABLE(1600, 1250, 1250, 2850, 1500, 950)
OPERATIONS
NUMTABLE()
Can someone explain why the
, ( select avg(column_value)
from table
( cast( d.salaries as numTable)
) Department_Avg_Salary
does not give an average per department but instead only the first department's average?
thanks for your help!
regards
Lucas Jellemascott@ORA92> select d.dname,
2 (select avg(column_value)
3 from table (cast (d.salaries as numTable))
4 where d.dname = dname) Department_Avg_Salary
5 from (select cast (multiset (select e.sal
6 from emp e
7 where e.deptno = d1.deptno) as numTable) salaries,
8 d1.dname
9 from dept d1) d
10 /
DNAME DEPARTMENT_AVG_SALARY
ACCOUNTING 2916.66667
RESEARCH 2175
SALES 1566.66667
OPERATIONS -
Select from a collection of collections SELECT - CAST - MULTISET - TABLE
Does someone have a suggestion for the SELECT statement which is performing a CAST?
I am on Oracle 10.2.0.1.0. The goal is to take a collection of a nested table and order it by color, then descr, then grown_by, saving it into an ordered collection (v_List2). Am getting error with ORA-22907 Invalid cast to a type that is not a nested table.
CREATE OR REPLACE TYPE ot_fruit
AS OBJECT
descr VARCHAR2(100)
,color VARCHAR2(50)
,grown_by VARCHAR2(50)
CREATE OR REPLACE TYPE tab_fruitList AS TABLE OF ot_fruit;
CREATE OR REPLACE TYPE ot_tab_fruit
AS OBJECT
fruit tab_fruitList
DECLARE
v_List ot_tab_fruit := ot_tab_fruit(tab_fruitList(ot_fruit('apple','red','tree'),
ot_fruit('blueberry','blue','bush')
v_List2 ot_tab_fruit := ot_tab_fruit(tab_fruitList());
BEGIN
SELECT CAST ( MULTISET ( SELECT * FROM TABLE(v_List)
ORDER BY 2, 3, 1
<b> -- This compiles with ORA-22907 error
AS ot_tab_fruit</b>
) INTO v_List2
FROM DUAL;
FOR i IN v_List2.FIRST..v_List2.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('i='||i||' descr='||v_List2(i).fruit.descr ||' color='||
v_List2(i).fruit.color||' grown_by='||v_List2(i).fruit.grown_by);
END LOOP;
END;Thanks, Kate
Message was edited by:
johnsokThis solution, which works perfectly by the way, came from Avi Abrami. I've highlighted the necessary changes to make the SELECT of a collection of objects work properly.
create or replace type OT_FRUIT as object (
DESCR varchar2(100)
,COLOR varchar2(50)
,GROWN_BY varchar2(50)
create or replace type TAB_FRUITLIST as table of OT_FRUIT;
create or replace type OT_TAB_FRUIT as object (
FRUIT TAB_FRUITLIST
DECLARE
v_List ot_tab_fruit := ot_tab_fruit(tab_fruitList(ot_fruit('apple','red','tree'),
ot_fruit('blueberry','blue','bush')
v_List2 ot_tab_fruit := ot_tab_fruit(tab_fruitList());
BEGIN
SELECT CAST ( MULTISET ( SELECT * FROM TABLE(v_List.fruit)
ORDER BY 2, 3, 1
AS tab_fruitlist
) INTO v_List2.fruit
FROM DUAL;
FOR i IN v_List2.fruit.FIRST..v_List2.fruit.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('i='||i||' descr='||v_List2.fruit(i).descr ||' color='||
v_List2.fruit(i).color||' grown_by='||v_List2.fruit(i).grown_by);
END LOOP;
END;
/ -
CAST MULTISET...is it supported by BI
In a precedent POst i explained the problems we had with multiple queries to display data as a hierarchical manner, with more than 2 levels
We'd like to explore the way with CAST MULTISET...but before to spend time, we'd like to assure that it is supported by BI Publisher.
As an example ( with one level):
We prepared the Object Types as is :
create or replace TYPE ETAG_T AS OBJECT("@S_NUME_OBJE" NUMBER,
S_NUME_ETAG NUMBER,
C_TYPE_ETAG VARCHAR2(4 CHAR),
L_DESC_ETAG VARCHAR2(50 CHAR),
N_NOMB_PIEC NUMBER,
N_SURF_TOTA NUMBER,
D_MODI DATE,
R_FONC CHAR(5),
R_UTIL CHAR(20),
C_CODE_LANG VARCHAR2(4 CHAR)
create or replace TYPE etaglist_t AS TABLE OF etag_t
create or replace TYPE obje_t as Object (
"@S_NUME_OBJE" NUMBER,
N_NUME_IMME VARCHAR2(5) ,
N_NUME_OBJE VARCHAR2(5) ,
etag_list etaglist_t
Then the data query is (Statement is named Q1):
SELECT
obje_t(s_nume_obje, n_nume_obje, n_nume_imme,
CAST (MULTISET (SELECT S_NUME_OBJE,
S_NUME_ETAG,
C_TYPE_ETAG,
L_DESC_ETAG,
N_NOMB_PIEC,
N_SURF_TOTA,
D_MODI,
R_FONC,
R_UTIL,
C_CODE_LANG
FROM imm.b12_0 eta
WHERE eta.s_nume_obje = obj.s_nume_obje)
AS etaglist_t))
AS "obj"
FROM pointi.b02_v obj
WHERE obj.s_nume_obje= :sNumeObje
As a result , we get only the <obj> element like this :
<LIST_Q1>
<Q1>
<obj/>
</Q1>
</LIST_Q1>
We tried too :
SELECT XMLElement("Object",
obje_t(s_nume_obje, n_nume_obje, n_nume_imme,
CAST (MULTISET (SELECT S_NUME_OBJE,
S_NUME_ETAG,
C_TYPE_ETAG,
L_DESC_ETAG,
N_NOMB_PIEC,
N_SURF_TOTA,
D_MODI,
R_FONC,
R_UTIL,
C_CODE_LANG
FROM imm.b12_0 eta
WHERE eta.s_nume_obje = obj.s_nume_obje)
AS etaglist_t))
AS "obj" ) as "objXML"
FROM pointi.b02_v obj
WHERE obj.s_nume_obje= :sNumeObje
And we get :
<Q1>
<objXML/>
</Q1>
Seems to be not supported isn't it...
LaurentOk thanks,
I already checked your blog before to speak about pl/sql tables ;-)
I think , for maintenance, it will better too , than having a single query with many cast...Multiset , which could have more than 500 lines :-(
But in our case, as we should have kind of hierarchies in the XML (with levels) and collections, i think we should have a mix :
store pl/sql tables in a package, that will be reused from the main query, and certainly continue to use cast multiset to manage theses nested collections.
As you said, i think we could remove the use of Object Types as we do today. -
CAST and MULTISET with nested table
I am trying to figure out the syntax of using
MULTISET. I have two queries.
One very basic where I want to cast the station names
and ids, retrieved from a regular table into a nested
table.
e.g.
SELECT cast(multiset(stn_id, stn_name) as castTab) FROM station_tab WHERE stn_name like '%xyz%';
The other retrieve sections of a nested table and cast back as
nested table type.
SELECT * FROM CAST(MULTISET(SELECT * FROM
THE (SELECT tmn_history FROM tmin WHERE tmn_stn_ncdcid = 01063456) NT
WHERE (EXTRACT(YEAR FROM NT.dta_date) = 1915) AS data_tab ;
The schema/tables are as follows
=========================================================================
CREATE TABLE station_tab
stn_id INTEGER PRIMARY KEY,
stn_name VARCHAR(50)
CREATE OR REPLACE TYPE data_point AS OBJECT
dta_date DATE,
dta_val NUMBER,
dta_dtobtnd DATE
CREATE OR REPLACE TYPE data_tab AS TABLE OF data_point;
CREATE TABLE tmin
tmn_stn_id INTEGER ,
tmn_history data_tab
) NESTED TABLE tmn_history STORE AS tmn_history_tab;
CREATE OR REPLACE TYPE castObj AS OBJECT
dta_val NUMBER,
stn_name VARCHAR(50)
CREATE OR REPLACE TYPE castTab AS TABLE OF castObj;
=====================================================================
Thank you.
barrWith trial and error and going thru the examples
in AskTom and documentation found that the follwing syntax works.
(Also realized this is the wrong forum);
SELECT * FROM TABLE (cast(multiset
(SELECT stn_ncdcid,stn_name FROM station_tab WHERE stn_name LIKE '%WSFO%')
AS castTab));
select * FROM TABLE (CAST(MULTISET (SELECT * FROM
THE (SELECT tmn_history FROM tmin WHERE tmn_stn_ncdcid = 01063456) NT
WHERE (EXTRACT(YEAR FROM NT.dta_date) = 1915)
ORDER BY NT.dta_date) as data_tab)) ; -
Unexpected result of multiset mapping in SQL
Please help me to confirm is that behavior explained below is a bug, or clearly explain why it's right. There are a high probability that I misunderstood some concept, but now for me it looks like a bug.
All examples below simplified as much as possible to demonstrate core of the issue. Real situation is very complex, so only general answers and workarounds related to principle of query construction is acceptable.
You are welcome to ask clarifying questions and i'll try to do my best to answer them.
Thank you for attention.
Question
Why in Example shown below collection instance in (select count(1) ...) subquery from first row mapped to all rows of the table, while expected result is to map each collection instance to it's own row?
At the same time collections used in cardinality(...) expression chosen properly.
Same situation (not covered in example) exists if constructed in this way collections used in from or where part of a query.
I can confirm this behavior on 10.2.0.5.0 (IBM/AIX), 11.2.0.2.0 (Win32) and 11.2.0.3.0 (IBM/AIX).
Note: my question with more details and examples can be found on stackoverflow.
Script for test environment setup
create or replace type TabType0 as table of varchar2(100)
create table Table0( tab_str_field varchar2(100), tab_field TabType0)
nested table tab_field store as tab_field_table
insert into table0 (tab_str_field, tab_field) values (
'A',
cast(multiset(
select 'A' from dual union all
select 'B' from dual union all
select 'C' from dual
) as TabType0)
insert into table0 (tab_str_field, tab_field) values (
'B',
cast(multiset(
select 'B' from dual union all
select 'C' from dual
) as TabType0)
insert into table0 (tab_str_field, tab_field) values (
'C',
cast(multiset(
select 'A' from dual union all
select 'B' from dual union all
select 'C' from dual union all
select 'D' from dual
) as TabType0)
insert into table0 (tab_str_field, tab_field) values (
'D',
cast(multiset(
select 'A' from dual
) as TabType0)
select 'Initial table data' caption from dual
select * from table0
Data inserted to table0:
| TAB_STR_FIELD | TAB_FIELD |
| A | A,B,C |
| B | B,C |
| C | A,B,C,D |
| D | A |
Example query
with string_set as (
select 'A' str_field from dual union all
select 'B' str_field from dual union all
select 'C' str_field from dual union all
select 'D' str_field from dual union all
select 'E' str_field from dual
select
table0_tab_field table0_tab_field,
set_tab_field set_tab_field,
-- cardinality
cardinality(table0_tab_field) table0_tab_cardinality,
cardinality(set_tab_field) set_tab_cardinality,
-- select from table field of current row
(select count(1) from table(set_tab_field)) set_tab_count,
-- select from field of current row while joining
-- with another field of same row
( select column_value from table(set_tab_field)
where column_value = table0_tab_str_field
) same_value
from (
select
table0.tab_str_field table0_tab_str_field,
table0.tab_field table0_tab_field,
cast(multiset(
select
string_set.str_field
from
string_set,
table(table0.tab_field) tab_table
where
string_set.str_field = tab_table.column_value
) as TabType0)
) set_tab_field
from
table0
Results of query execution
| TABLE0_TAB_FIELD | SET_TAB_FIELD | TABLE0_TAB_CARDINALITY | SET_TAB_CARDINALITY | SET_TAB_COUNT | SAME_VALUE |
| A,B,C | A,B,C | 3 | 3 | 3 | A |
| B,C | B,C | 2 | 2 | 3 | B |
| A,B,C,D | A,B,C,D | 4 | 4 | 3 | C |
| A | A | 1 | 1 | 3 | (null) |
Expected results
| TABLE0_TAB_FIELD | SET_TAB_FIELD | TABLE0_TAB_CARDINALITY | SET_TAB_CARDINALITY | SET_TAB_COUNT | SAME_VALUE |
| A,B,C | A,B,C | 3 | 3 | 3 | A |
| B,C | B,C | 2 | 2 | 2 | B |
| A,B,C,D | A,B,C,D | 4 | 4 | 4 | C |
| A | A | 1 | 1 | 1 | (null) |Sounds like a bug. Workaround:
with string_set as (
select 'A' str_field from dual union all
select 'B' str_field from dual union all
select 'C' str_field from dual union all
select 'D' str_field from dual union all
select 'E' str_field from dual
select table0_tab_field table0_tab_field,
set_tab_field set_tab_field,
-- cardinality
cardinality(table0_tab_field) table0_tab_cardinality,
cardinality(set_tab_field) set_tab_cardinality,
-- select from table field of current row
(select count(1) from table(set_tab_field)) set_tab_count,
-- select from field of current row while joining
-- with another field of same row
(select column_value from table(set_tab_field)
where column_value = table0_tab_str_field
) same_value
from (
select table0.tab_str_field table0_tab_str_field,
table0.tab_field table0_tab_field,
select cast(
multiset(
select string_set.str_field
from string_set,
table(table0.tab_field) tab_table
where string_set.str_field = tab_table.column_value
as TabType0
) from dual
) set_tab_field
from table0
TABLE0_TAB_FIELD SET_TAB_FIELD TABLE0_TAB_CARDINALITY SET_TAB_CARDINALITY SET_TAB_COUNT SAME_VALUE
TABTYPE0('A', 'B', 'C') TABTYPE0('A', 'B', 'C') 3 3 3 A
TABTYPE0('B', 'C') TABTYPE0('B', 'C') 2 2 2 B
TABTYPE0('A', 'B', 'C', 'D') TABTYPE0('A', 'B', 'C', 'D') 4 4 4 C
TABTYPE0('A') TABTYPE0('A') 1 1 1
SQL>
SY. -
Object view multi-cast problem
We are using the following object to generate XML the output for multi=cast is prodicing an unwanted extra tag "*_ITEM"
Any ideias??
CREATE OR REPLACE VIEW sjs.arrest_obj_view
AS SELECT CAST(MULTISET(SELECT 'ERROR NEEDED ' FROM dual) AS errors_type) AS "Errors",
a.a_date AS "ArrestDate",
NVL(a.a_photo_num,'NULL') AS "PhotographNumber",
NVL(a.a_division,'NULL') AS "AgencyDivision",
'MODEL MAPPING PROBLEM' AS "ArrestType",
NVL(agcy.agcy_ori,'NULL') AS "ArrestingAgency",
a.a_id AS "ArrestNumber",
NVL(oa.o_number,'NULL') AS "ArrestingOfficerID",
NVL(o.o_number,'NULL') AS "AssistingOfficerID",
'MODEL MAPPING PROBLEM' AS "AssistingAgency",
'MODEL MAPPING PROBLEM' AS "CJTN",
CAST(MULTISET(SELECT l.lu_name AS "Weapon"
FROM sjs.arrestweapons awm,
sjs.lookuptable l
WHERE awm.a_id = a.a_id
AND awm.weapons_id = lu_id (+)) AS arrest_weapons_type) AS "ArrestWeapons"
FROM sjs.arrest a,
sjs.agency agcy,
sjs.officers o,
sjs.officers oa
WHERE a.agcy_id = agcy.agcy_id (+)
AND a.o_arrest_id = oa.o_id (+)
AND a.o_assist_id = o.o_id (+)
- <ROWSET>
- <ROW num="1">
<InterfaceTransaction>ADD</InterfaceTransaction>
<Resubmission>RESUBMISSION NEEDED</Resubmission>
<SubmittingAgency>NY1111111</SubmittingAgency>
<SubmittingEmployeeID>FFOTI</SubmittingEmployeeID>
<TOT>TOT NEEDED</TOT>
- <Errors>
- <Errors_ITEM>
<Error>ERROR NEEDED</Error>
</Errors_ITEM>
</Errors>
<ArrestDate>3/18/2002 9:40:0</ArrestDate>
<PhotographNumber>PPPPP</PhotographNumber>
<AgencyDivision>PPP</AgencyDivision>
<ArrestType>MODEL MAPPING PROBLEM</ArrestType>
<ArrestingAgency>NY1111111</ArrestingAgency>
<ArrestNumber>1</ArrestNumber>
<ArrestingOfficerID>NULL</ArrestingOfficerID>
<AssistingOfficerID>NULL</AssistingOfficerID>
<AssistingAgency>MODEL MAPPING PROBLEM</AssistingAgency>
<CJTN>MODEL MAPPING PROBLEM</CJTN>
- <ArrestWeapons>
- <ArrestWeapons_ITEM>
<Weapon>FULLY AUTOMATIC RIFLE OR MACHINE GUN</Weapon>
</ArrestWeapons_ITEM>
- <ArrestWeapons_ITEM>
<Weapon>FIRE/INCENDIARY DEVICE</Weapon>
</ArrestWeapons_ITEM>
</ArrestWeapons>
</ROW>
</ROWSET>How would you replace the multi-cast within the object with cursor?
Thanks -
Can we use multiset and with clause both
Please let me know how to use both multiset and with clause.
You need one more inlining, as e.g. in:
SQL> select *
from table (cast (multiset (select *
from (with t as (select deptno from dept)
select * from t)) as sys.dbms_debug_vc2coll))
COLUMN_VALUE
10
20
30
40
50
5 rows selected. -
Can't see the output of cast/multicast
Hi, I can't see the output of cast/multicast.. but in sql*plus, i can..
regardsHello, here's a sample...
ops$rringor@RLR9204> create or replace type
2 myarraytype as table of varchar2(2000)
3 /
Type created.
ops$rringor@RLR9204> drop table t;
Table dropped.
ops$rringor@RLR9204> create table t
2 ( id number not null ,
3 name varchar2(10) ) ;
Table created.
ops$rringor@RLR9204> begin
2 for i in 1..10
3 loop
4 insert into t values ( i, i||'abc');
5 end loop;
6 end;
7 /
PL/SQL procedure successfully completed.
ops$rringor@RLR9204>
ops$rringor@RLR9204> select a.id,
2 CAST( MULTISET( select b.name
3 from t b
4 where b.id = a.id ) as myArrayType ) as names
5 from t a ;
ID NAMES
1 MYARRAYTYPE('1abc')
2 MYARRAYTYPE('2abc')
3 MYARRAYTYPE('3abc')
4 MYARRAYTYPE('4abc')
5 MYARRAYTYPE('5abc')
6 MYARRAYTYPE('6abc')
7 MYARRAYTYPE('7abc')
8 MYARRAYTYPE('8abc')
9 MYARRAYTYPE('9abc')
10 MYARRAYTYPE('10abc')
10 rows selected.
I can see the records under NAMES but I can't view it using SQLDeveloper. -
Refer Multiset Union value from cursor
Hi everyone,
I am new to the concept of pseudo functiona and was just trying to use the multiset union function. I have written a cursor which gives me a column 'buyer' and a corresponding dataset. Now my dilemna is how to refer the elements in the dataset using the cursor. Could anyone please help?
CREATE TABLE BUYER
BUYER NUMBER(4) NOT NULL,
BUYER_NAME VARCHAR2(120 BYTE) NOT NULL,
BUYER_PHONE VARCHAR2(20 BYTE),
BUYER_FAX VARCHAR2(20 BYTE)
SET DEFINE OFF;
Insert into RMS.BUYER
(BUYER, BUYER_NAME, BUYER_PHONE, BUYER_FAX)
Values
(110, 'Kendr', '5147, 876', NULL);
Insert into RMS.BUYER
(BUYER, BUYER_NAME, BUYER_PHONE, BUYER_FAX)
Values
(101, 'Amelie Dube', '(514),808', NULL);
Insert into RMS.BUYER
(BUYER, BUYER_NAME, BUYER_PHONE, BUYER_FAX)
Values
(102, 'Jennifer Baie', '51962,860', NULL);
Insert into RMS.BUYER
(BUYER, BUYER_NAME, BUYER_PHONE, BUYER_FAX)
Values
(103, 'Loriannstris', '5333962,785', NULL);
Insert into RMS.BUYER
(BUYER, BUYER_NAME, BUYER_PHONE, BUYER_FAX)
Values
(104, 'Sandra St-re', '513962,736', NULL);
COMMIT;
create or replace type tab1 is table of varchar2 (30);
DECLARE
cursor c1 is
select buyer,
CAST (multiset(select buyer_name from buyer where rownum<4) as tab1) as data1
from buyer
MULTISET UNION ALL
select buyer,
CAST(multiset(select buyer_name from buyer where rownum<5) as tab1) as data2
from buyer;
BEGIN
for c_rec in c1
loop
DBMS_OUTPUT.PUT_LINE(c_rec.buyer||'~'||c_rec.column_value(1)); -- i want to print all the values in the 'data set' along with the buyer id.
end loop;
end;
error:
PLS-00302: component 'COLUMN_VALUE' must be declaredThanks a lot for your help. Now the one i posted was just to simplify the actual problem. But let me try and give you the complete picture.
I have a nested table structure:
Table structure:
->ExtOfXOrderSkuDesc_TBL -> ExtOfOrderExpDesc_TBL
I_message -> ExtOfXOrderDesc_TBL
->ExtOfXOrderPackDesc_TBL -> ExtOfOrderExpDesc_TBLCould not post the whole table detail as its too big
CURSOR c_insert_item IS
SELECT im.item,
item_diff.import_country_id,
item_diff.hts_no,
item_diff.ExtOfOrderExpDesc_TBL --needs to be casted
FROM TABLE(CAST(I_message.ExtOfXOrderDesc_TBL(1).ExtOfXOrderSkuDesc_TBL AS "RIB_ExtOfXOrderSkuDesc_TBL")) item_diff,
item_master im
WHERE item_diff.style_no = im.item_parent
UNION ALL
SELECT im.item,
pack_diff.import_country_id,
pack_diff.hts_no,
pack_diff.ExtOfOrderExpDesc_TBL --needs to be casted
FROM TABLE(CAST(I_message.ExtOfXOrderDesc_TBL(1).ExtOfXOrderPackDesc_TBL AS "RIB_ExtOfXOrderPackDesc_TBL")) pack_diff,
item_master im
WHERE pack_diff.style_no = im.item_parent;Now i need to make an union of all the elements including the ExtOfOrderExpDesc_TBL . So i wanted the cast it as multiset. But pardon my ignorance i feel i am lost somewhere. Based on you reply could you suggest how can i make the union and access each element using the cursor record?
Thanks
Maybe you are looking for
-
Updating from 9.1.6 to 9.1.8
I purchased and installed the retail version of Logic Studio 2 a couple of years ago. The Logic Pro version currently on my computer is 9.1.6. I get this message when trying to update: An eligible Logic Pro version was not found in the Applications f
-
My itunes wont work for my itouch
i just got a new computer for christmas, and my old one crashed, so i got a software that took all my songs off my ipod and saved them to my computer, i installed itunes and when i plugged it in it would not reconize it as my itouches main computer,
-
Is there a way to keep the perspective when switching cameras with an external monitor? When I switch cameras to say front, the output on the mx02 is not the same as on the monitor, the monitor will center the image, full screen by default but the mx
-
How does Taxware work....
Can anyone tell me what is Taxware.... a) Is it a software package....standalone client or webclient....? b) how it interacts with R/3 c)Any document with Taxware know-hows...please forward... Thanks Gita
-
How to make new column in table changing depending on other columns
hi i have table and i want to add new column that calculate the deference between two other columns. i create the column and i could loop in the content of the table but i could not update the entries in the new columns. regards Said