From MOS: Transient Objects by COLLECT Function (Doc ID 1603706.1)
SYMPTOMS
Transient objects for created Type left over when using CAST(COLLECT()) even when the session closed
SQL> select * from user_objects where object_name like 'SYSTP%';
no rows selected
SQL> create type varchar2_tt as table of varchar2(4000);
Type created.
SQL> create or replace view vw as
select object_type,
cast(collect(object_name) as varchar2_tt) as object_names
from user_objects
group by object_type ;
View created.
SQL> select * from user_objects where object_name like 'SYSTP%';
OBJECT_NAME
------------------------------------------------------------------------------
--
SUBOBJECT_NAME OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE
------------------------------ ---------- -------------- -------------------
CREATED LAST_DDL_ TIMESTAMP STATUS T G S NAMESPACE
--------- --------- ------------------- ------- - - - ----------
EDITION_NAME
------------------------------
SYSTP4A8EEzKtQPLgQwEAAH9H2Q==
77213 TYPE
26-JUN-13 26-JUN-13 2013-06-26:14:45:32 VALID N N N 1
SQL> purge recyclebin ;
Recyclebin purged.
SQL> select * from user_objects where object_name like 'SYSTP%';
OBJECT_NAME
------------------------------------------------------------------------------
--
SUBOBJECT_NAME OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE
------------------------------ ---------- -------------- -------------------
CREATED LAST_DDL_ TIMESTAMP STATUS T G S NAMESPACE
--------- --------- ------------------- ------- - - - ----------
EDITION_NAME
------------------------------
SYSTP4A8EEzKtQPLgQwEAAH9H2Q==
77213 TYPE
26-JUN-13 26-JUN-13 2013-06-26:14:45:32 VALID N N N 1
SQL>exit
SQL>conn SH/SH
SQL> create or replace view vw as
select object_type,
cast(collect(object_name) as varchar2_tt) as object_names
from user_objects
group by object_type ;
View created.
SQL> select * from user_objects where object_name like 'SYSTP%';
OBJECT_NAME
------------------------------------------------------------------------------
--
SUBOBJECT_NAME OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE
------------------------------ ---------- -------------- -------------------
CREATED LAST_DDL_ TIMESTAMP STATUS T G S NAMESPACE
--------- --------- ------------------- ------- - - - ----------
EDITION_NAME
------------------------------
SYSTP4A8EEzKtQPLgQwEAAH9H2Q==
77213 TYPE
26-JUN-13 26-JUN-13 2013-06-26:14:45:32 VALID N N N 1
CHANGES
Even when the session exist for every creation of the view that will use CAST(COLLECT()) a new transient object will be created
CAUSE
The functionality of the cleanup of the Transient objects by SMON is designed to be called every 12 hours
This is expected as per design
Following Query Could be used to check for objects that is not cleaned by SMON after 12 hours :
alter session set nls_date_format = 'dd/mm/yyyy hh24:mi:ss';
col owner for a30
col object_name for a30
col created for a30
SQL>select owner,object_name,created,TRUNC((sysdate - created) * 24)
from dba_objects
where object_name like 'SYSTP%'
and TRUNC((sysdate - created) * 24) > 12
order by 3,4,2 ;
SOLUTION
1.start the instance with pfile where this event is set :
*.event="22834 trace name context forever, level 5"
This will enforce SMON to clean-up those transient objects every 5 minutes . The default interval between cleanups is 12 hrs. When the clean up function
is called first, if no interval was specified at the time, it will wait for 12 hrs before getting executed again. If you have set 22834 level 5, it will wait 12 hrs and then get called every 5 minutes. But for it to be active from the beginning the event + level has to be set up at DB start time.
=====================================
You can see this in your demo
SQL> create table t as select chr(ascii('a')-1+rownum) x from dual connect by level <= 4;
Table created.
SQL> create or replace type sample_ntt is table of varchar2(10);
2 /
Type created.
SQL> select object_name, last_ddl_time from user_objects where object_type = 'TYPE' order by 2;
OBJECT_NAME LAST_DDL_TIME
---------------------------------------- --------------------
SAMPLE_NTT 28-may-2016 09:11:26
SQL> select cast( collect(x) as sample_ntt) from t;
CAST(COLLECT(X)ASSAMPLE_NTT)
---------------------------------------------------------------------------------------------------
SAMPLE_NTT('a', 'b', 'c', 'd')
SQL> select object_name, last_ddl_time from user_objects where object_type = 'TYPE' order by 2;
OBJECT_NAME LAST_DDL_TIME
---------------------------------------- --------------------
SAMPLE_NTT 28-may-2016 09:11:26
SYSTP4Pnv/j/vSwOdfASNad25UQ== 28-may-2016 09:12:11
SQL> select * from table( powermultiset( sample_ntt('a','b','c','d')) ) ;
COLUMN_VALUE
---------------------------------------------------------------------------------------------------
SAMPLE_NTT('a')
SAMPLE_NTT('b')
SAMPLE_NTT('a', 'b')
SAMPLE_NTT('c')
SAMPLE_NTT('a', 'c')
SAMPLE_NTT('b', 'c')
SAMPLE_NTT('a', 'b', 'c')
SAMPLE_NTT('d')
SAMPLE_NTT('a', 'd')
SAMPLE_NTT('b', 'd')
SAMPLE_NTT('a', 'b', 'd')
SAMPLE_NTT('c', 'd')
SAMPLE_NTT('a', 'c', 'd')
SAMPLE_NTT('b', 'c', 'd')
SAMPLE_NTT('a', 'b', 'c', 'd')
15 rows selected.
SQL> select object_name, last_ddl_time from user_objects where object_type = 'TYPE' order by 2;
OBJECT_NAME LAST_DDL_TIME
---------------------------------------- --------------------
SAMPLE_NTT 28-may-2016 09:11:26
SYSTP4Pnv/j/vSwOdfASNad25UQ== 28-may-2016 09:12:11
SYSTPnNZ6+836Tp+yWuozQnktmA== 28-may-2016 09:12:11
SQL> select * from table( powermultiset_by_cardinality( sample_ntt('a','b','c','d') ,2) ) ;
COLUMN_VALUE
---------------------------------------------------------------------------------------------------
SAMPLE_NTT('a', 'b')
SAMPLE_NTT('a', 'c')
SAMPLE_NTT('a', 'd')
SAMPLE_NTT('b', 'c')
SAMPLE_NTT('b', 'd')
SAMPLE_NTT('c', 'd')
6 rows selected.
SQL> select object_name, last_ddl_time from user_objects where object_type = 'TYPE' order by 2;
OBJECT_NAME LAST_DDL_TIME
---------------------------------------- --------------------
SAMPLE_NTT 28-may-2016 09:11:26
SYSTP4Pnv/j/vSwOdfASNad25UQ== 28-may-2016 09:12:11
SYSTPnNZ6+836Tp+yWuozQnktmA== 28-may-2016 09:12:11
My inference is that collect must return "something", so the type is created on the fly, and *then* that type is cast into the one you specified.