TABLE function to simulate parameterized view
Hi all,
Since view can not have parameters, I tried to used stored procedure to return ref cursor then used TABLE function in select statement to simulate a view with parameters, since it's easy to pass parameters to a stored procedure.
The idea is like this
function foo (p1 int, p2 int)
return sys_ref_cursor
c sys_ref_cursor -- sorry, i forgot the buildin ref cursor name, just used
this as pseudo code
is
open c for select * from table_a where col1=:p1 and col2=p2 using p1, p2;
return c;
end;
select * from table(foo(1,2)) does not work, I know that I can iterate throught
the cursor and pipe it out to a SQL type in function foo, then use TABLE
function in SELECT statement. However, it seems so much coding work. Is it the
only way or do you have better idea?
Thanks in advance.
It is just not correct that you cannot parameterize views.
Nicolas gave you a link above which has an example using a context.
Even before Oracle supported contexts you could have parameterize views using package variables.
SQL> create or replace package pkg_vars as
2 function get_job return emp.job%type;
3 procedure set_job (p_job in emp.job%type)
4 end pkg_vars;
5 /
Package created.
SQL>
SQL> create or replace package body pkg_vars as
2 g_job emp.job%type;
3
4 function get_job return emp.job%type)
5 is
6 begin
7 return g_job;
8 end get_job;
9
10 procedure set_job (p_job in emp.job%type
11 is
12 begin
13 g_job := p_job;
14 end set_job;
15 end pkg_vars;
16 /
Package body created.
SQL>
SQL> create or replace view view_emp1 as
2 select deptno, count(empno) cnt
3 from emp
4 where job = pkg_vars.get_job
5 group by deptno
6 ;
View created.
SQL> select distinct job from emp;
JOB
CLERK
SALESMAN
PRESIDENT
MANAGER
ANALYST
5 rows selected.
SQL> exec pkg_vars.set_job('CLERK');
PL/SQL procedure successfully completed.
SQL> select * from view_emp1;
DEPTNO CNT
30 1
20 2
10 1
SQL> exec pkg_vars.set_job('MANAGER');
PL/SQL procedure successfully completed.
SQL> select * from view_emp1;
DEPTNO CNT
30 1
20 1
10 1
SQL>
Similar Messages
-
TABLE FUNCTION - Using database view - send parameters to the function.
Hi everybody:
1.- I have a function returning a TABLE OF, and that function recieve 2 parameters of type NUMBER.
2.- I'm able to call this function as a table function like this:
SELECT * FROM TABLE(my_function(3,4))
3.- I want to create a database View, To use this query in diferent places of my app.
CREATE OR REPLACE VIEW NAME_OF_MY_VIEW AS SELECT * FROM TABLE(my_function(:_idOne,:idTwo))
4.- My problem is, that I want to send the parameters dinamically to the function, and use those parameters to populate the rows, using a database view, the previous code does not compile... and I don't know another way to do this.
Please help.
thnks in advance.
Alex.Yes you can:
SQL> CREATE PACKAGE pkg
AS
a_global VARCHAR2 (30);
FUNCTION f (a VARCHAR2)
RETURN varchar_tab;
FUNCTION ret_global
RETURN VARCHAR2;
FUNCTION set_ret_global (ret_global VARCHAR2)
RETURN INTEGER;
END;
Package created.
SQL> CREATE OR REPLACE PACKAGE BODY pkg
AS
FUNCTION f (a VARCHAR2)
RETURN varchar_tab
AS
l_varchar_tab varchar_tab := varchar_tab ();
BEGIN
FOR i IN 1 .. 10
LOOP
l_varchar_tab.EXTEND;
l_varchar_tab (i) := a;
END LOOP;
RETURN l_varchar_tab;
END f;
FUNCTION ret_global
RETURN VARCHAR2
AS
BEGIN
RETURN a_global;
END ret_global;
FUNCTION set_ret_global (ret_global VARCHAR2)
RETURN INTEGER
AS
BEGIN
a_global := ret_global;
RETURN 1;
END set_ret_global;
END pkg;
Package body created.
SQL> CREATE OR REPLACE VIEW v
AS
SELECT *
FROM TABLE (pkg.f (pkg.ret_global))
View created.
SQL> SELECT *
FROM v
WHERE 1 = pkg.set_ret_global (5)
COLUMN_VALUE
5
5
5
5
5
5
5
5
5
5
10 rows selected.
SQL> SELECT *
FROM v
WHERE 1 = pkg.set_ret_global (4)
COLUMN_VALUE
4
4
4
4
4
4
4
4
4
4
10 rows selected. -
How to define a view on a table function
I have a defined a pipelined table function in a package and can return data from it using:
select * from table(mtreport.FN_GET_JOBS_FOR_PROJECT(?));How can I define a view on this so that users can select from it without having to know to use the 'table' syntax?
select *
from vw_jobs_for_project
where id = ?I've tried this, but it doesn't work
CREATE OR REPLACE VIEW vw_jobs_for_project (PROJECT_ID, NAME) AS
SELECT PROJECT_ID, NAME
FROM table(mtreport.FN_GET_JOBS_FOR_PROJECT(PROJECT_ID));
ERROR at line 3:
ORA-00904: "PROJECT_ID": invalid identifierviews do not accept input parameters in the way that you want to use. you can define a CONTEXT parameter, but the users would need to set the context value before selecting from the view, so you'll still need to train them to do something new.
example:
create or replace context my_context using pkg_context;
<br>
create or replace package pkg_context is
procedure set_context(p_parameter in varchar2, p_value in varchar2);
function get_context(p_parameter in varchar2) return varchar2;
end;
show errors
create or replace package body pkg_context is
CONTEXT_NAME constant all_context.namespace%type := 'MY_CONTEXT';
procedure set_context(p_parameter in varchar2, p_value in varchar2) is
begin
dbms_session.set_context(CONTEXT_NAME, p_parameter, p_value);
end;
function get_context(p_parameter in varchar2) return varchar2 is
begin
return sys_context(CONTEXT_NAME, p_parameter);
end;
end;
show errors
create or replace view tree_view as
select level lvl, chid
from tree
connect by prior parid=chid
start with chid = sys_context('MY_CONTEXT','CHID');
-- at runtime
exec pkg_context.set_context('CHID', 14)
select * from tree_view; -
Interactive report on view based on pipelined table function.
Hi,
I want to build an Interactive Report on a view.
The view definition contains a select on a pipelined table function. I use context functionality to pass paramaters to the pipelined table function.
A plain select * from #my_view# in SqlPlus results in 121 different rows.
However, If I base my Interactive report on this view, I get 15 repeated rows (all the same).
Is it possible to use pipelined table functionality on an Interactive report? I can't seem to get it working.
If I use the following approach (http://rakeshjsr.blogspot.nl/2010/10/oracle-apex-interactive-report-based-on.html) I do get results, but I can't use this solution for a reason that's not relevant.Hello,
Is it possible to use pipelined table functionality on an Interactive report? I can't seem to get it working. I have used it in one instance and it works fine. However I was passing the values to pipe-lined function directly.
IR Query..
SELECT * FROM TABLE(fn_pipeline(:P1_ITEM_NAME))Call pipe-lined function from IR query directly (instead of using view)
Try sending values to Pipe-lined function directly. In-case if the problem is with setting and getting values from the context?
Regards,
Hari -
Text Index works fine consistently with Table, but not on underlying View
Hi,
We are facing weird issue relating to Oracle Text Indexes. Search using Oracle Text Index
works fine on a Table, but when running query on View it gives sometimes (not consistently)
ORA-20000: Oracle Text error:
DRG-10849: catsearch does not support functional invocation
DRG-10599: column is not indexed
Sometimes it works.
All of the below steps are run using User IR2OWNER:
STEP 1: Table CPF_CUSTOMER created as follows (3 Non Text Indexes defined at time of creation )
**Please note no Public Synonym is created for this Table**
** There is already another Table by same name CPF_CUSTOMER under different Owner (CDROWNER)
and that Table has Public Synonym CPF_CUSTOMER created. Other Table CPF_CUSTOMER does not
have any Views **
create table CPF_CUSTOMER
CPF_CUSTOMER_UUID NUMBER(20) not null,
SAP_ID VARCHAR2(10 CHAR) not null,
IRIS2_ID VARCHAR2(7 CHAR),
NAME VARCHAR2(70 CHAR) not null,
DRAFT_IND NUMBER(1) not null,
ACTIVE_IND NUMBER(1) not null,
REPLACED_BY_CUST VARCHAR2(10 CHAR),
CRE_DT_GMT DATE,
CRE_DT_LOC DATE,
TIME_ZONE VARCHAR2(3 CHAR),
CRE_USR VARCHAR2(8 CHAR),
CHG_DT_GMT DATE,
CHG_DT_LOC DATE,
CHG_TIME_ZONE VARCHAR2(3 CHAR),
CHG_USR VARCHAR2(8 CHAR),
VFY_DT_GMT DATE,
VFY_DT_LOC DATE,
VFY_USR VARCHAR2(8 CHAR),
DIVISION VARCHAR2(20 CHAR),
SALES_ADMIN VARCHAR2(3 CHAR),
MF_CUST_CDE VARCHAR2(14 CHAR),
CR_CTRL_OFCE VARCHAR2(3 CHAR),
DEFAULT_INV_CCY VARCHAR2(3 CHAR),
AUTOBILL_OVRRD_IND NUMBER(1) not null,
AUTOBILL NUMBER(1) not null,
AUTOPRT_OVRRD_IND NUMBER(1) not null,
AUTOPRT NUMBER(1) not null,
AVE_PYMT_DAY NUMBER(3),
TTL_INV_VAL NUMBER(12,2),
INHERIT_CR_TERM_ASSGMT NUMBER(1) not null,
NORMALIZED_NME VARCHAR2(70 CHAR),
OB_PYMT_OFCE VARCHAR2(3 CHAR),
IB_PYMT_OFCE VARCHAR2(3 CHAR),
CGO_SMART_ID VARCHAR2(20 CHAR),
REC_UPD_DT TIMESTAMP(6),
NCPF_CUST_ID VARCHAR2(7) not null,
CPF_CUST_LEVEL_UUID NUMBER(20) not null
tablespace DBCPFP1_LG_DATA LOGGING;
CREATE UNIQUE INDEX CPF_CUSTOMERI1 ON CPF_CUSTOMER
(SAP_ID ASC) TABLESPACE DBCPFP1_LG_INDX;
ALTER TABLE CPF_CUSTOMER
ADD CONSTRAINT CPF_CUSTOMERI1 UNIQUE (SAP_ID);
CREATE UNIQUE INDEX CPF_CUSTOMERI2 ON CPF_CUSTOMER
(CPF_CUSTOMER_UUID ASC) TABLESPACE DBCPFP1_LG_INDX;
ALTER TABLE CPF_CUSTOMER
ADD CONSTRAINT CPF_CUSTOMERI2 UNIQUE (CPF_CUSTOMER_UUID);
CREATE INDEX CPF_CUSTOMER_IDX2 ON CPF_CUSTOMER (UPPER(NAME))
TABLESPACE DBCPFP1_LG_INDX;
STEP 2: Create View CPF_CUSTOMER_RVW on above Table (and Public Synonym on View)
This View is created under same OWNER as Table created in STEP 1 (IR2OWNER)
create or replace view cpf_customer_rvw as
select
CPF_CUSTOMER_UUID,
SAP_ID,
IRIS2_ID,
NAME,
DRAFT_IND,
ACTIVE_IND,
REPLACED_BY_CUST,
CRE_DT_GMT,
CRE_DT_LOC,
TIME_ZONE,
CRE_USR,
CHG_DT_GMT,
CHG_DT_LOC,
CHG_TIME_ZONE,
CHG_USR,
VFY_DT_GMT,
VFY_DT_LOC,
VFY_USR,
DIVISION,
SALES_ADMIN,
MF_CUST_CDE,
CR_CTRL_OFCE,
DEFAULT_INV_CCY,
AUTOBILL_OVRRD_IND,
AUTOBILL,
AUTOPRT_OVRRD_IND,
AUTOPRT,
AVE_PYMT_DAY,
TTL_INV_VAL,
INHERIT_CR_TERM_ASSGMT,
NORMALIZED_NME,
OB_PYMT_OFCE,
IB_PYMT_OFCE,
CGO_SMART_ID,
NCPF_CUST_ID,
CPF_CUST_LEVEL_UUID,
REC_UPD_DT
from CPF_CUSTOMER;
CREATE OR REPLACE PUBLIC SYNONYM CPF_CUSTOMER_RVW FOR CPF_CUSTOMER_RVW;
STEP 3: Insert Test row
insert into cpf_customer (CPF_CUSTOMER_UUID, SAP_ID, IRIS2_ID, NAME, DRAFT_IND, ACTIVE_IND, REPLACED_BY_CUST, CRE_DT_GMT, CRE_DT_LOC, TIME_ZONE, CRE_USR, CHG_DT_GMT, CHG_DT_LOC, CHG_TIME_ZONE, CHG_USR, VFY_DT_GMT, VFY_DT_LOC, VFY_USR, DIVISION, SALES_ADMIN, MF_CUST_CDE, CR_CTRL_OFCE, DEFAULT_INV_CCY, AUTOBILL_OVRRD_IND, AUTOBILL, AUTOPRT_OVRRD_IND, AUTOPRT, AVE_PYMT_DAY, TTL_INV_VAL, INHERIT_CR_TERM_ASSGMT, NORMALIZED_NME, OB_PYMT_OFCE, IB_PYMT_OFCE, CGO_SMART_ID, NCPF_CUST_ID, CPF_CUST_LEVEL_UUID, REC_UPD_DT)
values (2.26283572796028E15, '6588125000', '6588125', 'S M Mooseen And Sons(PVT) Limited', 0, 1, '', to_date('15-03-2005 08:55:00', 'dd-mm-yyyy hh24:mi:ss'), to_date('15-03-2005 14:25:00', 'dd-mm-yyyy hh24:mi:ss'), 'IST', 'licr2', to_date('19-02-2007 00:33:00', 'dd-mm-yyyy hh24:mi:ss'), to_date('19-02-2007 06:03:00', 'dd-mm-yyyy hh24:mi:ss'), 'IST', 'BaseAdmi', to_date('15-03-2005 09:03:00', 'dd-mm-yyyy hh24:mi:ss'), to_date('15-03-2005 14:33:00', 'dd-mm-yyyy hh24:mi:ss'), 'ninwasa', '', '', 'SRI06588125000', '463', '', 0, 0, 0, 0, null, null, 0, 'SMMOOSEENANDSONSPVTLIMITED', '', '', '', '6588125', 109966195050333, '14-JAN-09 02.49.28.325774 PM');
commit;
STEP 4: Create Oracle Text Index on Table CPF_CUSTOMER
EXEC CTX_DDL.DROP_PREFERENCE('CTXCAT_IR2_STORAGE');
EXEC CTX_DDL.CREATE_PREFERENCE('CTXCAT_IR2_STORAGE', 'BASIC_STORAGE');
EXEC CTX_DDL.SET_ATTRIBUTE('CTXCAT_IR2_STORAGE', 'I_INDEX_CLAUSE', 'TABLESPACE COMMON_SM_INDX COMPRESS 2');
EXEC CTX_DDL.SET_ATTRIBUTE('CTXCAT_IR2_STORAGE', 'I_INDEX_CLAUSE', 'TABLESPACE COMMON_SM_INDX COMPRESS 2');
EXEC CTX_DDL.SET_ATTRIBUTE('CTXCAT_IR2_STORAGE', 'K_TABLE_CLAUSE', 'TABLESPACE COMMON_SM_INDX COMPRESS 2');
EXEC CTX_DDL.SET_ATTRIBUTE('CTXCAT_IR2_STORAGE', 'R_TABLE_CLAUSE', 'TABLESPACE COMMON_SM_INDX COMPRESS 2');
EXEC CTX_DDL.SET_ATTRIBUTE('CTXCAT_IR2_STORAGE', 'I_ROWID_INDEX_CLAUSE', 'TABLESPACE COMMON_SM_INDX storage (INITIAL 5M)');
-- Define IR2_AB_LEXER to handle Special Characters.
EXEC ctx_ddl.drop_preference('IR2_AB_LEXER');
EXEC ctx_ddl.create_preference('IR2_AB_LEXER', 'BASIC_LEXER');
EXEC ctx_ddl.set_attribute ('IR2_AB_LEXER', 'printjoins', ',_!$~%?=({;|&+-:/)}.@`^');
--Drop Indexes
drop index CPF_CUSTOMER_DIDX1;
-- CATSEARCH INDEX on CPF_CUSTOMER.NAME
CREATE INDEX CPF_CUSTOMER_DIDX1 ON CPF_CUSTOMER(NAME) INDEXTYPE IS CTXSYS.CTXCAT PARAMETERS ('STORAGE CTXCAT_IR2_STORAGE STOPLIST CTXSYS.EMPTY_STOPLIST LEXER IR2_AB_LEXER');
commit;
STEP 5: Run Query to use Oracle Text Index on Base Table (works fine always. No issues seen so far)
SELECT a.sap_id||'|'||a.name||'|' CUSTOMER_STR
FROM cpf_customer a
WHERE (catsearch(a.name, 'Mooseen'||'*', '')>0);
CUSTOMER_STR
6588125000|S M Mooseen And Sons(PVT) Limited|
STEP 6: Run Query to use Oracle Text Index on View created under Table (get below error periodically)
ORA-20000: Oracle Text error:
DRG-10849: catsearch does not support functional invocation
DRG-10599: column is not indexed
But it works sometimes as in STEP 5 and returns 1 row. It is never consistent. We would like to
provide access to this Table using View only. That is why we would like to get this query working consistently
using View.
Any help or tips would be greatly appreciated
Thanks
AuroThis is a known issue with CTXCAT indexes. Sometimes the optimizer will "drive" the query off another index, and request results from the CTXCAT index on a row-by-row basis ("does the row with rowid NNNN satisfy this CATSEARCH condition?"). That's known as a functional lookup, and is not supported by the CTXCAT indextype.
The only solution is to try to persuade the optimizer to use a different plan which does not use a functional lookup. This can be achieved by the use of hints, or sometimes by collecting or deleting statistics on the table. -
Parameterized Views for User Reports
I would like to be able to define a view such as:
create view dept_emps(p_dept in varchar2) as
select * from emps where dept = p_dept);
and use this view to define a SQL Dev drilldown report with SQL such as:
select * from dept_emps(:DEPT)
where :DEPT is a bind variable passed from a selected depts report row.
Oracle apparently does not support parameterized view definitions as suggested above, but I have found an article by Tom Kyte on the issue of parameterizing views, where Tom suggests using DBMS_SESSION.SET_CONTEXT (called within a user package) to set context values that can be retrieved in a view using the SYS_CONTEXT function. I can get this approach to work at the SQL prompt to work around the lack of formal view parameters. I have a package which defines a procedure which sets context values that I can then retrieve within a view using the SYS_CONTEXT function.
To use this approach when defining a SQL Developer user report, the SQL for the report would need to be logically something like (which works fine at an SQL prompt):
exec ssuper_context.set_ctx('DEPT', :DEPT) - - Call user procedure to assign context variable 'DEPT' with bind value from parent report
select * from dept_emps
where view dept_emps uses function SYS_CONTEXT to return the value for context variable 'DEPT'.
SQL Developer complains about this as the SQL for a user-defined report. Can anyone suggest how I might pass a bind value from a selected parent record to a view which implements a drilldown report?
TIA JonI met CSI at a kongress a few weeks ago and pressed them a bit on how this works. Eventually they fezzed up about the table read but mentioned that in the next release being developed it would be different...
Problems with this is that the FM has a couple of limitations, so you cannot read all tables correctly... so you end up reading some of the wrong ones or taking the easy ones.
Another option is to let the database itself do the hard work, to get back to the performance aspect.
Anyway, for neither of these two do you need any tcode, so indeed we are drifting off topic... -
OWB9.0.4 Table Function
Can someone post valid code for use as a table function. It's a new concept to me and I can't seem to come up with a function I can use by the Table function operator.
What I'm trying to do is populate a calendar table (date, month, year, quarter, etc.) by providing a start date and an end date.Paul,
Here is the link to Table Functions documentation, from the PL/SQL point of view, together with some examples:
http://otn.oracle.com/docs/products/oracle9i/doc_library/release2/appdev.920/a96624/08_subs.htm#19677
The current implementation of table functions in OWB is limited - it will be improved in the next versions. You will have to write and deploy the table function manually to the target database. Then you will have to create a table function operator whose signature (input and output parameters) match the function you created in the target environment (otherwise, you will have problems deploying it). At the moment, the input parameter can be one or more ref-cursors type and/or a scalars, while the output will be a table type.
Regards:
Igor -
How to use database look up table function in xsl mapping
Can anybody tell me how to use database look up table function while mapping xsl between 2 nodes.
I have an XML file coming in and depending on one of XML elements we need to decide which further path to take. But, using this XML element, we need to query database table, get metadata and accordingly take appropriate path. I have written lookup function which returns metadata value.
Now, the issue is how do I pass the XML element valu as input to look up function? When I tried to drag it to the input node of lookup function, it throws an error like "Maximum number of parameters exceeded"
Thanks,If the lookup table is always going to remain the same (e.g. a character generator or something similar) you can place the values in a 2D array constant on your diagram, with the input value as one column, the equivalent as the other. When you need to perform the lookup you use an index array to return all the values in the "input column", search it using "search 1D array" and use the resulting index number to index the other column's data. If the values may change, then it would probably be best to load an array control with your equivalent values from a file.
P.M.
Putnam
Certified LabVIEW Developer
Senior Test Engineer
Currently using LV 6.1-LabVIEW 2012, RT8.5
LabVIEW Champion -
TABLE function not working in Dreamweaver
Dreamweaver MX on Vista. My table function has simply stopped
working or existing in my program. Everything else still works
properly. When I change Table view it does not matter. When I press
the table tab or icon, absolutely nothing happens and no windows
appear to enter values. Is this a common glitch or is something
selected that I do not know about that may have caused such?
Thanks.The suggestion to make changes to the Configuration-1 files
is wrong. This
is a folder created by DW when you re-install it (it's the
old configuration
folder). It's not used during normal operation.
Murray --- ICQ 71997575
Adobe Community Expert
(If you *MUST* email me, don't LAUGH when you do so!)
==================
http://www.projectseven.com/go
- DW FAQs, Tutorials & Resources
http://www.dwfaq.com - DW FAQs,
Tutorials & Resources
==================
"Ken Binney" <[email protected]> wrote
in message
news:gka7ns$hhb$[email protected]..
> Here is one solution
>
>
http://www.funkytower.com/2008/09/22/dreamweaver-mx-and-vista-fix-insert-tables-best-fix/
>
> "MediaQ4U" <[email protected]> wrote in
message
> news:gk9pl2$1kn$[email protected]..
>> Dreamweaver MX on Vista. My table function has
simply stopped working or
>> existing in my program. Everything else still works
properly. When I
>> change
>> Table view it does not matter. When I press the
table tab or icon,
>> absolutely
>> nothing happens and no windows appear to enter
values. Is this a common
>> glitch
>> or is something selected that I do not know about
that may have caused
>> such?
>>
>> Thanks.
>>
>
> -
Can AnyOne Explain Parameterized View with Example
Explain the parameterized view with example
Cathrin wrote:
Hi ,
I have created a view...
CREATE OR REPLACE VIEW V_UNITS_UNITMOVEMENT_AMTEST(fromdate varchar,todate varchar)
... 127 more lines (no kidding)
Group By A.Code,A.UDate,B.Scheme_Description,A.DividendOption,C.DividendType_Name,A.NAV,A.Units
when i execute i get this error ...
ORA-00907: missing right parenthesis
what should i do?First, indent your code to show the extent of structures that extend over several lines, such as subqueries, CASE expressions, or function calls that have nexted arguments.
Make parentheses line up so that, if a ) has to be lines away from its matching (, then are indented the same amount, with nothing except white space between them.
When posting code (or any formatted text) on this site, type these 6 characters:
\(small letters only, inside curly brackets) before and after sections of formatted text, to preserve spacing.
Note that "ORA-00907: missing right parenthesis" doesn't always mean you have unbalanced parentheses. Often, it just means that something (such as an Oracle keyword) appears at a point where it doesn't make sense, but where a ) would make sense.
Second, develop code in very small increments. Take baby steps. Start with a very small, simple query, test it, then add one or two more lines. When you get a mysterious error like "ORA-00907: missing right parenthesis", chances are there was a mistake in the one or two lines you just added. -
How get list of tables/functions/other objects used in a mapping?
Hi,
I would like to know list of objects such as tables, views, functions, procedures and table functions of all mappings in a module.
Could any one please explain me, how can I do this using OMB+ scripting.
Thank you,
Regards,
Gowtham Sen.OMBRETRIEVE MAPPING 'MAP_NAME' GET TABLE OPERATORS
OMBRETRIEVE MAPPING 'MAP_NAME' GET VIEW OPERATORS
OMBRETRIEVE MAPPING 'MAP_NAME' GET TRANSFORMATION OPERATORS
OMBRETRIEVE MAPPING 'MAP_NAME' GET TABLE_FUNCTION OPERATORS
Alternative variant (and maybe more simple) - use dictionary view DBA_DEPENDENCIES (or all_dependencies):
select * from dba_dependencies where owner='MAP_OWNER' and type in ('PACKAGE','PACKAGE_BODY') and name='MAP_NAME'
Oleg -
Creating parameterized views in oracle11g
I have a big query with nesting and left join and Ineed to create a view out of it so as not to run it from the application. The issue is I need the date range and some other fields as input parameters since it will vary from the front end for each request. I just looked up and saw some posts referring to using SYS_CONTEXT for parameterized views and need to know exactly how do I create the view for example with 2 parameters - fromdate, todate and how I invoke the view from the application.
Just for info I am using grails/groovy for developing the application. and here is the query I want to create view out of..
select
d.dateInRange as dateval,
eventdesc,
nvl(td.dist_ucnt, 0) as dist_ucnt
from (
select
to_date(fromdate,'dd-mon-yyyy') + rownum - 1 as dateInRange
from all_objects
where rownum <= to_date(fromdate,'dd-mon-yyyy') - to_date(todate,'dd-mon-yyyy') + 1
) d
left join (
select
to_char(user_transaction.transdate,'dd-mon-yyyy') as currentdate,
count(distinct(grauser_id)) as dist_ucnt,
eventdesc
from
gratransaction, user_transaction
where gratransaction.id = user_transaction.trans_id and
user_transaction.transdate between to_date(fromdate,'dd-mon-yyyy') and to_date(todate,'dd-mon-yyyy')
group by to_char(user_transaction.transdate, 'dd-mon-yyyy'), eventdesc
) td on td.currentdate = d.dateInRange order by d.dateInRange ascuser12985447 wrote:
I have a big query with nesting and left join and Ineed to create a view out of it so as not to run it from the application. The issue is I need the date range and some other fields as input parameters since it will vary from the front end for each request. I just looked up and saw some posts referring to using SYS_CONTEXT for parameterized views and need to know exactly how do I create the view for example with 2 parameters - fromdate, todate and how I invoke the view from the application.
Just for info I am using grails/groovy for developing the application. and here is the query I want to create view out of..
select
d.dateInRange as dateval,
eventdesc,
nvl(td.dist_ucnt, 0) as dist_ucnt
from (
select
to_date(fromdate,'dd-mon-yyyy') + rownum - 1 as dateInRange
from all_objects
where rownum <= to_date(fromdate,'dd-mon-yyyy') - to_date(todate,'dd-mon-yyyy') + 1
) d
left join (
select
to_char(user_transaction.transdate,'dd-mon-yyyy') as currentdate,
count(distinct(grauser_id)) as dist_ucnt,
eventdesc
from
gratransaction, user_transaction
where gratransaction.id = user_transaction.trans_id and
user_transaction.transdate between to_date(fromdate,'dd-mon-yyyy') and to_date(todate,'dd-mon-yyyy')
group by to_char(user_transaction.transdate, 'dd-mon-yyyy'), eventdesc
) td on td.currentdate = d.dateInRange order by d.dateInRange ascAre you dead set on creating a view? If so ... why?
I'd recommend creating a stored procedure / function (in a package) that returns a ref cursor before i'd recommend what you're going for (unless there is some extremely compelling reason why only a view will work). -
Usage of TAble Functions in OBIEE
Hello All,
I have created a table function in the database.
Is it possible to use/call table functions in obiee.Please let me know how to use table functions in OBIEE.
Thanks in advance.Hi,
Thanks for your reply.
I want to use this table function to generate answers report.
In the query i am using unions,bind variables.I can not create a database view on this query.The best solution would be creating a table function.
But,i do not know how to access/use/call this table function to create answers report.
Thanks in advance. -
10g: delay for collecting results from parallel pipelined table functions
When parallel pipelined table functions are properly started and generate output record, there is a delay for the consuming main thread to gather these records.
This delay is huge compared with the run-time of the worker threads.
For my application it goes like this:
main thread timing efforts to start worker and collect their results:
[10:50:33-*10:50:49*]:JOMA: create (master): 015.93 sec (#66356 records, #4165/sec)
worker threads:
[10:50:34-*10:50:39*]:JOMA: create (slave) : 005.24 sec (#2449 EDRs, #467/sec, #0 errored / #6430 EBTMs, #1227/sec, #0 errored) - bulk #1 / sid #816
[10:50:34-*10:50:39*]:JOMA: create (slave) : 005.56 sec (#2543 EDRs, #457/sec, #0 errored / #6792 EBTMs, #1221/sec, #0 errored) - bulk #1 / sid #718
[10:50:34-*10:50:39*]:JOMA: create (slave) : 005.69 sec (#2610 EDRs, #459/sec, #0 errored / #6950 EBTMs, #1221/sec, #0 errored) - bulk #1 / sid #614
[10:50:34-*10:50:39*]:JOMA: create (slave) : 005.55 sec (#2548 EDRs, #459/sec, #0 errored / #6744 EBTMs, #1216/sec, #0 errored) - bulk #1 / sid #590
[10:50:34-*10:50:39*]:JOMA: create (slave) : 005.33 sec (#2461 EDRs, #462/sec, #0 errored / #6504 EBTMs, #1220/sec, #0 errored) - bulk #1 / sid #508
You can see, the worker threads are all started at the same time and terminating at the same time: 10:50:34-10:50:*39*.
But the main thread just invoking them and saving their results into a collection has finished at 10:50:*49*.
Why does it need #10 sec more just to save the data?
Here's a sample sqlplus script to demonstrate this:
--------------------------- snip -------------------------------------------------------
set serveroutput on;
drop table perf_data;
drop table test_table;
drop table tmp_test_table;
drop type ton_t;
drop type test_list;
drop type test_obj;
create table perf_data
sid number,
t1 timestamp with time zone,
t2 timestamp with time zone,
client varchar2(256)
create table test_table
a number(19,0),
b timestamp with time zone,
c varchar2(256)
create global temporary table tmp_test_table
a number(19,0),
b timestamp with time zone,
c varchar2(256)
create or replace type test_obj as object(
a number(19,0),
b timestamp with time zone,
c varchar2(256)
create or replace type test_list as table of test_obj;
create or replace type ton_t as table of number;
create or replace package test_pkg
as
type test_rec is record (
a number(19,0),
b timestamp with time zone,
c varchar2(256)
type test_tab is table of test_rec;
type test_cur is ref cursor return test_rec;
function TZDeltaToMilliseconds(
t1 in timestamp with time zone,
t2 in timestamp with time zone)
return pls_integer;
function TF(mycur test_cur)
return test_list pipelined
parallel_enable(partition mycur by hash(a));
end;
create or replace package body test_pkg
as
* Calculate timestamp with timezone difference
* in milliseconds
function TZDeltaToMilliseconds(
t1 in timestamp with time zone,
t2 in timestamp with time zone)
return pls_integer
is
begin
return (extract(hour from t2) - extract(hour from t1)) * 3600 * 1000
+ (extract(minute from t2) - extract(minute from t1)) * 60 * 1000
+ (extract(second from t2) - extract(second from t1)) * 1000;
end TZDeltaToMilliseconds;
function TF(mycur test_cur)
return test_list pipelined
parallel_enable(partition mycur by hash(a))
is
pragma autonomous_transaction;
sid number;
counter number(19,0) := 0;
myrec test_rec;
mytab test_tab;
mytab2 test_list := test_list();
t1 timestamp with time zone;
t2 timestamp with time zone;
begin
t1 := systimestamp;
select userenv('SID') into sid from dual;
dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): enter');
loop
fetch mycur into myRec;
exit when mycur%NOTFOUND;
mytab2.extend;
mytab2(mytab2.last) := test_obj(myRec.a, myRec.b, myRec.c);
end loop;
for i in mytab2.first..mytab2.last loop
-- attention: saves own SID in test_obj.a for indication to caller
-- how many sids have been involved
pipe row(test_obj(sid, mytab2(i).b, mytab2(i).c));
pipe row(test_obj(sid, mytab2(i).b, mytab2(i).c)); -- duplicate
pipe row(test_obj(sid, mytab2(i).b, mytab2(i).c)); -- duplicate once again
counter := counter + 1;
end loop;
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'slave');
commit;
dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): exit, piped #' || counter || ' records');
end;
end;
declare
myList test_list := test_list();
myList2 test_list := test_list();
sids ton_t := ton_t();
sid number;
t1 timestamp with time zone;
t2 timestamp with time zone;
procedure LogPerfTable
is
type ton is table of number;
type tot is table of timestamp with time zone;
type clients_t is table of varchar2(256);
sids ton;
t1s tot;
t2s tot;
clients clients_t;
deltaTime integer;
btsPerSecond number(19,0);
edrsPerSecond number(19,0);
begin
select sid, t1, t2, client bulk collect into sids, t1s, t2s, clients from perf_data order by client;
if clients.count > 0 then
for i in clients.FIRST .. clients.LAST loop
deltaTime := test_pkg.TZDeltaToMilliseconds(t1s(i), t2s(i));
if deltaTime = 0 then deltaTime := 1; end if;
dbms_output.put_line(
'[' || to_char(t1s(i), 'hh:mi:ss') ||
'-' || to_char(t2s(i), 'hh:mi:ss') ||
']:' ||
' client ' || clients(i) || ' / sid #' || sids(i)
end loop;
end if;
end LogPerfTable;
begin
select userenv('SID') into sid from dual;
for i in 1..200000 loop
myList.extend; myList(myList.last) := test_obj(i, sysdate, to_char(i+2));
end loop;
-- save into the real table
insert into test_table select * from table(cast (myList as test_list));
-- save into the tmp table
insert into tmp_test_table select * from table(cast (myList as test_list));
dbms_output.put_line(chr(10) || '(1) copy ''mylist'' to ''mylist2'' by streaming via table function...');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from table(cast (myList as test_list)) tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
dbms_output.put_line(chr(10) || '(2) copy temporary ''tmp_test_table'' to ''mylist2'' by streaming via table function:');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from tmp_test_table tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
dbms_output.put_line(chr(10) || '(3) copy physical ''test_table'' to ''mylist2'' by streaming via table function:');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
end;
--------------------------- snap -------------------------------------------------------
best regards,
FrankHello
I think the delay you are seeing is down to choosing the partitioning method as HASH. When you specify anything other than ANY, an additional buffer sort is included in the execution plan...
create or replace package test_pkg
as
type test_rec is record (
a number(19,0),
b timestamp with time zone,
c varchar2(256)
type test_tab is table of test_rec;
type test_cur is ref cursor return test_rec;
function TZDeltaToMilliseconds(
t1 in timestamp with time zone,
t2 in timestamp with time zone)
return pls_integer;
function TF(mycur test_cur)
return test_list pipelined
parallel_enable(partition mycur by hash(a));
function TF_Any(mycur test_cur)
return test_list pipelined
parallel_enable(partition mycur by ANY);
end;
create or replace package body test_pkg
as
* Calculate timestamp with timezone difference
* in milliseconds
function TZDeltaToMilliseconds(
t1 in timestamp with time zone,
t2 in timestamp with time zone)
return pls_integer
is
begin
return (extract(hour from t2) - extract(hour from t1)) * 3600 * 1000
+ (extract(minute from t2) - extract(minute from t1)) * 60 * 1000
+ (extract(second from t2) - extract(second from t1)) * 1000;
end TZDeltaToMilliseconds;
function TF(mycur test_cur)
return test_list pipelined
parallel_enable(partition mycur by hash(a))
is
pragma autonomous_transaction;
sid number;
counter number(19,0) := 0;
myrec test_rec;
t1 timestamp with time zone;
t2 timestamp with time zone;
begin
t1 := systimestamp;
select userenv('SID') into sid from dual;
dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): enter');
loop
fetch mycur into myRec;
exit when mycur%NOTFOUND;
-- attention: saves own SID in test_obj.a for indication to caller
-- how many sids have been involved
pipe row(test_obj(sid, myRec.b, myRec.c));
pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate
pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate once again
counter := counter + 1;
end loop;
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'slave');
commit;
dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): exit, piped #' || counter || ' records');
end;
function TF_any(mycur test_cur)
return test_list pipelined
parallel_enable(partition mycur by ANY)
is
pragma autonomous_transaction;
sid number;
counter number(19,0) := 0;
myrec test_rec;
t1 timestamp with time zone;
t2 timestamp with time zone;
begin
t1 := systimestamp;
select userenv('SID') into sid from dual;
dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): enter');
loop
fetch mycur into myRec;
exit when mycur%NOTFOUND;
-- attention: saves own SID in test_obj.a for indication to caller
-- how many sids have been involved
pipe row(test_obj(sid, myRec.b, myRec.c));
pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate
pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate once again
counter := counter + 1;
end loop;
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'slave');
commit;
dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): exit, piped #' || counter || ' records');
end;
end;
explain plan for
select /*+ first_rows */ test_obj(a, b, c)
from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
select * from table(dbms_xplan.display);
Plan hash value: 1037943675
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
| 0 | SELECT STATEMENT | | 8168 | 3972K| 20 (0)| 00:00:01 | | | |
| 1 | PX COORDINATOR | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10001 | 8168 | 3972K| 20 (0)| 00:00:01 | Q1,01 | P->S | QC (RAND) |
| 3 | BUFFER SORT | | 8168 | 3972K| | | Q1,01 | PCWP | |
| 4 | VIEW | | 8168 | 3972K| 20 (0)| 00:00:01 | Q1,01 | PCWP | |
| 5 | COLLECTION ITERATOR PICKLER FETCH| TF | | | | | Q1,01 | PCWP | |
| 6 | PX RECEIVE | | 931K| 140M| 136 (2)| 00:00:02 | Q1,01 | PCWP | |
| 7 | PX SEND HASH | :TQ10000 | 931K| 140M| 136 (2)| 00:00:02 | Q1,00 | P->P | HASH |
| 8 | PX BLOCK ITERATOR | | 931K| 140M| 136 (2)| 00:00:02 | Q1,00 | PCWC | |
| 9 | TABLE ACCESS FULL | TEST_TABLE | 931K| 140M| 136 (2)| 00:00:02 | Q1,00 | PCWP | |
Note
- dynamic sampling used for this statement
explain plan for
select /*+ first_rows */ test_obj(a, b, c)
from table(test_pkg.TF_Any(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
select * from table(dbms_xplan.display);
Plan hash value: 4097140875
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
| 0 | SELECT STATEMENT | | 8168 | 3972K| 20 (0)| 00:00:01 | | | |
| 1 | PX COORDINATOR | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10000 | 8168 | 3972K| 20 (0)| 00:00:01 | Q1,00 | P->S | QC (RAND) |
| 3 | VIEW | | 8168 | 3972K| 20 (0)| 00:00:01 | Q1,00 | PCWP | |
| 4 | COLLECTION ITERATOR PICKLER FETCH| TF_ANY | | | | | Q1,00 | PCWP | |
| 5 | PX BLOCK ITERATOR | | 931K| 140M| 136 (2)| 00:00:02 | Q1,00 | PCWC | |
| 6 | TABLE ACCESS FULL | TEST_TABLE | 931K| 140M| 136 (2)| 00:00:02 | Q1,00 | PCWP | |
Note
- dynamic sampling used for this statementI posted about it here a few years ago and I more recently posted a question on Asktom. Unfortunately Tom was not able to find a technical reason for it to be there so I'm still a little in the dark as to why it is needed. The original question I posted is here:
Pipelined function partition by hash has extra sort#
I ran your tests with HASH vs ANY and the results are in line with the observations above....
declare
myList test_list := test_list();
myList2 test_list := test_list();
sids ton_t := ton_t();
sid number;
t1 timestamp with time zone;
t2 timestamp with time zone;
procedure LogPerfTable
is
type ton is table of number;
type tot is table of timestamp with time zone;
type clients_t is table of varchar2(256);
sids ton;
t1s tot;
t2s tot;
clients clients_t;
deltaTime integer;
btsPerSecond number(19,0);
edrsPerSecond number(19,0);
begin
select sid, t1, t2, client bulk collect into sids, t1s, t2s, clients from perf_data order by client;
if clients.count > 0 then
for i in clients.FIRST .. clients.LAST loop
deltaTime := test_pkg.TZDeltaToMilliseconds(t1s(i), t2s(i));
if deltaTime = 0 then deltaTime := 1; end if;
dbms_output.put_line(
'[' || to_char(t1s(i), 'hh:mi:ss') ||
'-' || to_char(t2s(i), 'hh:mi:ss') ||
']:' ||
' client ' || clients(i) || ' / sid #' || sids(i)
end loop;
end if;
end LogPerfTable;
begin
select userenv('SID') into sid from dual;
for i in 1..200000 loop
myList.extend; myList(myList.last) := test_obj(i, sysdate, to_char(i+2));
end loop;
-- save into the real table
insert into test_table select * from table(cast (myList as test_list));
-- save into the tmp table
insert into tmp_test_table select * from table(cast (myList as test_list));
dbms_output.put_line(chr(10) || '(1) copy ''mylist'' to ''mylist2'' by streaming via table function...');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from table(cast (myList as test_list)) tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
dbms_output.put_line(chr(10) || '(2) copy temporary ''tmp_test_table'' to ''mylist2'' by streaming via table function:');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from tmp_test_table tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
dbms_output.put_line(chr(10) || '(3) copy physical ''test_table'' to ''mylist2'' by streaming via table function:');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
dbms_output.put_line(chr(10) || '(4) copy temporary ''tmp_test_table'' to ''mylist2'' by streaming via table function ANY:');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF_any(CURSOR(select /*+ parallel(tab,5) */ * from tmp_test_table tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
dbms_output.put_line(chr(10) || '(5) copy physical ''test_table'' to ''mylist2'' by streaming via table function using ANY:');
delete from perf_data;
t1 := systimestamp;
select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
from table(test_pkg.TF_any(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
t2 := systimestamp;
insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
LogPerfTable;
dbms_output.put_line('... saved #' || myList2.count || ' records');
select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
end;
(1) copy 'mylist' to 'mylist2' by streaming via table function...
test_pkg.TF( sid => '918' ): enter
test_pkg.TF( sid => '918' ): exit, piped #200000 records
[01:40:19-01:40:29]: client master / sid #918
[01:40:19-01:40:29]: client slave / sid #918
... saved #600000 records
(2) copy temporary 'tmp_test_table' to 'mylist2' by streaming via table function:
[01:40:31-01:40:36]: client master / sid #918
[01:40:31-01:40:32]: client slave / sid #659
[01:40:31-01:40:32]: client slave / sid #880
[01:40:31-01:40:32]: client slave / sid #1045
[01:40:31-01:40:32]: client slave / sid #963
[01:40:31-01:40:32]: client slave / sid #712
... saved #600000 records
(3) copy physical 'test_table' to 'mylist2' by streaming via table function:
[01:40:37-01:41:05]: client master / sid #918
[01:40:37-01:40:42]: client slave / sid #738
[01:40:37-01:40:42]: client slave / sid #568
[01:40:37-01:40:42]: client slave / sid #618
[01:40:37-01:40:42]: client slave / sid #659
[01:40:37-01:40:42]: client slave / sid #963
... saved #3000000 records
(4) copy temporary 'tmp_test_table' to 'mylist2' by streaming via table function ANY:
[01:41:12-01:41:16]: client master / sid #918
[01:41:12-01:41:16]: client slave / sid #712
[01:41:12-01:41:16]: client slave / sid #1045
[01:41:12-01:41:16]: client slave / sid #681
[01:41:12-01:41:16]: client slave / sid #754
[01:41:12-01:41:16]: client slave / sid #880
... saved #600000 records
(5) copy physical 'test_table' to 'mylist2' by streaming via table function using ANY:
[01:41:18-01:41:38]: client master / sid #918
[01:41:18-01:41:38]: client slave / sid #681
[01:41:18-01:41:38]: client slave / sid #712
[01:41:18-01:41:38]: client slave / sid #754
[01:41:18-01:41:37]: client slave / sid #880
[01:41:18-01:41:38]: client slave / sid #1045
... saved #3000000 recordsHTH
David -
Parallel pipelined table function, autonomous_transaction to global tmp tab
Hi,
i try to speed up my parallel pipelined table function and switch from pl/sql collection to global temporary table inside.
This requires to use PRAGMA AUTONOMOUS_TRANSACTION (and commit), because inserting into global temporary table (DML)
within select - for invoking the table function - is not allowed without.
As a consequence of commit it next requires to have on commit preserve rows for the global temporary table.
Now:
Inserts into the global temporary table are done - indicated by sql%rowcount.
But a select afterwards doesn't show any record anymore.
Here is a program to demonstrate it:
set serveroutput on;
drop type TestTableOfNumber_t;
create or replace type TestTableOfNumber_t is table of number;
drop type TestStatusList;
drop type TestStatusObj;
create or replace type TestStatusObj as object(
sid number,
ctr1 number,
ctr2 number,
ctr3 number
create or replace type TestStatusList is table of TestStatusObj;
drop table TestTmpTable;
create global temporary table TestTmpTable (
value number
) on commit preserve rows;
create or replace package test_pkg
as
type TestStatusRec is record (
sid number,
ctr1 number,
ctr2 number,
ctr3 number
type TestStatusTab is table of TestStatusRec;
function FillTmpTable(id in varchar2)
return TestStatusRec;
FUNCTION ptf (p_cursor IN sys_refcursor)
RETURN TestStatusList PIPELINED
PARALLEL_ENABLE(PARTITION p_cursor BY any);
end;
create or replace package body test_pkg
as
function FillTmpTable(id in varchar2)
return TestStatusRec
is
PRAGMA AUTONOMOUS_TRANSACTION;
result TestStatusRec;
sid number;
type ton is table of number;
tids TestTableOfNumber_t := TestTableOfNumber_t();
records number := 0;
begin
select userenv('SID') into sid from dual;
result.sid := sid;
delete from TestTmpTable;
for i in 1..100 loop
tids.extend;
tids(tids.last) := i;
end loop;
forall i in 1..tids.count
insert into TestTmpTable (value) values (tids(i));
-- get number of records inserted
records := sql%rowcount;
result.ctr1 := records;
-- retrieve again before commit
select count(*) into records from TestTmpTable;
result.ctr2 := records;
commit;
-- retrieve again after commit
select count(*) into records from TestTmpTable;
result.ctr3 := records;
return result;
end;
FUNCTION ptf (p_cursor IN sys_refcursor)
RETURN TestStatusList PIPELINED
PARALLEL_ENABLE(PARTITION p_cursor BY any)
IS
rec test_pkg.TestStatusRec;
value number;
sid number;
ctr integer := 0;
BEGIN
select userenv('SID') into sid from dual;
rec := FillTmpTable('IN PTF');
LOOP
FETCH p_cursor into value;
EXIT WHEN p_cursor%NOTFOUND;
ctr := ctr + 1;
END LOOP;
-- as a result i am only interested in the results of FillTmpTable():
PIPE ROW (TestStatusObj(rec.sid, rec.ctr1, rec.ctr2, rec.ctr3));
RETURN;
END;
end;
declare
tons TestTableOfNumber_t;
counts TestTableOfNumber_t;
status test_pkg.TestStatusRec;
statusList test_pkg.TestStatusTab;
begin
status := test_pkg.FillTmpTable('MAIN');
dbms_output.put_line('main thread:'
|| ' sid #' || status.sid
|| ' / #' || status.ctr1 || ' inserted '
|| ' / #' || status.ctr2 || ' before commit'
|| ' / #' || status.ctr3 || ' after commit');
select value bulk collect into tons from TestTmpTable;
select * bulk collect into statusList from TABLE(test_pkg.ptf(CURSOR(select /*+ parallel(tab,2) */ value from TestTmpTable tab)));
for i in 1..StatusList.count loop
dbms_output.put_line('worker thread #' || i || ':'
|| ' sid #' || statusList(i).sid
|| ' / #' || statusList(i).ctr1 || ' inserted '
|| ' / #' || statusList(i).ctr2 || ' before commit'
|| ' / #' || statusList(i).ctr3 || ' after commit');
end loop;
end;
/The output is:
main thread: sid #881 / #100 inserted / #100 before commit / #100 after commit
worker thread #1: sid #421 / #100 inserted / #0 before commit / #0 after commit
worker thread #2: sid #321 / #100 inserted / #0 before commit / #0 after commitThe 1st line is for the main thread invoking FillTmpTable().
The next #2 lines are for the worker threads of the parallel pipelined table function for invoking the same FillTmpTable().
For the main thread everything is as expected.
But for the worker threads the logs for before commit and after commit both give #0 for the number of available records in the global temporary table.
However all indicate #100 for the SQL insert
regards,
Frank
Edited by: user8704911 on Jul 7, 2011 10:13 AM
Edited by: user8704911 on Jul 7, 2011 10:20 AM
Edited by: user8704911 on Jul 7, 2011 10:27 AMSQL> select * from v$version;
BANNER
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
PL/SQL Release 11.1.0.7.0 - Production
CORE 11.1.0.7.0 Production
TNS for Linux: Version 11.1.0.7.0 - Production
NLSRTL Version 11.1.0.7.0 - Production
SQL> set serveroutput on;
SQL> drop type TestTableOfNumber;
drop type TestTableOfNumber
ERROR at line 1:
ORA-04043: object TESTTABLEOFNUMBER does not exist
SQL> /
drop type TestTableOfNumber
ERROR at line 1:
ORA-04043: object TESTTABLEOFNUMBER does not exist
SQL>
SQL> create or replace type TestTableOfNumber_t is table of number;
2 /
Type created.
SQL>
SQL> drop type TestStatusObj;
drop type TestStatusObj
ERROR at line 1:
ORA-04043: object TESTSTATUSOBJ does not exist
SQL> /
drop type TestStatusObj
ERROR at line 1:
ORA-04043: object TESTSTATUSOBJ does not exist
SQL>
SQL> create or replace type TestStatusObj as object(
2 sid number,
3 ctr1 number,
4 ctr2 number,
5 ctr3 number
6 );
7 /
Type created.
SQL>
SQL> drop type TestStatusList;
drop type TestStatusList
ERROR at line 1:
ORA-04043: object TESTSTATUSLIST does not exist
SQL> /
drop type TestStatusList
ERROR at line 1:
ORA-04043: object TESTSTATUSLIST does not exist
SQL>
SQL> create or replace type TestStatusList is table of TestStatusObj;
2 /
Type created.
SQL>
SQL> drop table TestTmpTable;
drop table TestTmpTable
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> /
drop table TestTmpTable
ERROR at line 1:
ORA-00942: table or view does not exist
SQL>
SQL> create global temporary table TestTmpTable (
2 value number
3 ) on commit preserve rows;
Table created.
SQL> /
create global temporary table TestTmpTable (
ERROR at line 1:
ORA-00955: name is already used by an existing object
SQL>
SQL> create or replace package test_pkg
2 as
3
4 type TestStatusRec is record (
5 sid number,
6 ctr1 number,
7 ctr2 number,
8 ctr3 number
9 );
10
11 type TestStatusTab is table of TestStatusRec;
12
13 function FillTmpTable(id in varchar2)
14 return TestStatusRec;
15
16 FUNCTION ptf (p_cursor IN sys_refcursor)
17 RETURN TestStatusList PIPELINED
18 PARALLEL_ENABLE(PARTITION p_cursor BY any);
19
20 end;
21 /
Package created.
SQL>
SQL> create or replace package body test_pkg
2 as
3
4 function FillTmpTable(id in varchar2)
5 return TestStatusRec
6 is
7 PRAGMA AUTONOMOUS_TRANSACTION;
8
9 result TestStatusRec;
10
11 sid number;
12
13 type ton is table of number;
14 tids TestTableOfNumber_t := TestTableOfNumber_t();
15
16 records number := 0;
17 begin
18 select userenv('SID') into sid from dual;
19 result.sid := sid;
20
21 delete from TestTmpTable;
22
23 for i in 1..100 loop
24 tids.extend;
25 tids(tids.last) := i;
26 end loop;
27
28 forall i in 1..tids.count
29 insert into TestTmpTable (value) values (tids(i));
30
31 -- get number of records inserted
32 records := sql%rowcount;
33 result.ctr1 := records;
34
35 -- retrieve again before commit
36 select count(*) into records from TestTmpTable;
37 result.ctr2 := records;
38
39 commit;
40
41 -- retrieve again after commit
42 select count(*) into records from TestTmpTable;
43 result.ctr3 := records;
44
45 return result;
46 end;
47
48 FUNCTION ptf (p_cursor IN sys_refcursor)
49 RETURN TestStatusList PIPELINED
50 PARALLEL_ENABLE(PARTITION p_cursor BY any)
51 IS
52 rec test_pkg.TestStatusRec;
53 value number;
54 sid number;
55 ctr integer := 0;
56 BEGIN
57 select userenv('SID') into sid from dual;
58 rec := FillTmpTable('IN PTF');
59 LOOP
60 FETCH p_cursor into value;
61 EXIT WHEN p_cursor%NOTFOUND;
62 ctr := ctr + 1;
63 END LOOP;
64
65 -- as a result i am only interested in the results of FillTmpTable():
66 PIPE ROW (TestStatusObj(rec.sid, rec.ctr1, rec.ctr2, rec.ctr3));
67
68 RETURN;
69 END;
70 end;
71 /
Package body created.
SQL>
SQL> declare
2 tons TestTableOfNumber_t;
3 counts TestTableOfNumber_t;
4 status test_pkg.TestStatusRec;
5 statusList test_pkg.TestStatusTab;
6 begin
7 status := test_pkg.FillTmpTable('MAIN');
8 dbms_output.put_line('main thread:'
9 || ' sid #' || status.sid
10 || ' / #' || status.ctr1 || ' inserted '
11 || ' / #' || status.ctr2 || ' before commit'
12 || ' / #' || status.ctr3 || ' after commit');
13
14 select value bulk collect into tons from TestTmpTable;
15
16 select * bulk collect into statusList from TABLE(test_pkg.ptf(CURSOR(select /*+ parallel(tab,2
) */ value from TestTmpTable tab)));
17
18 for i in 1..StatusList.count loop
19 dbms_output.put_line('worker thread #' || i || ':'
20 || ' sid #' || statusList(i).sid
21 || ' / #' || statusList(i).ctr1 || ' inserted '
22 || ' / #' || statusList(i).ctr2 || ' before commit'
23 || ' / #' || statusList(i).ctr3 || ' after commit');
24 end loop;
25
26 end;
27 /
main thread: sid #1023 / #100 inserted / #100 before commit / #100 after commit
worker thread #1: sid #1045 / #100 inserted / #100 before commit / #100 after
commit
worker thread #2: sid #1019 / #100 inserted / #100 before commit / #100 after
commit
PL/SQL procedure successfully completed.
SQL> I am getting a different result.
Regards
Raj
Maybe you are looking for
-
I have a Mac Mini late 2012 version and i am trying to reset to factory setting.
Hello, I had a bought a Mac Mini late 2012 version a couple months ago, and after i tried to install "pro tool" on my Mac, and FAILED. my Garage band wouldn't open anymore. it only tells me "garage band quit unexpectedly" when i open it. I tried unin
-
Apple ID on App store NOT mine.
I am trying to sign onto my app store. It is giving me an email that is not even mine to sign into. In my settings, it is saying my correct email. Then I go into the app store and this email pops up again and I'm not able to change it! I HELP! I have
-
Sybase TEXT to Oracle CLOB migration
Hi All, We are doing the migration from Sybase to Oracle 10g. Migration steps include.. 1. Creation of Oracle staging area similar structure as Sybase database. 2. Extract the data through BCP 3. Import to oracle by Sqlldr (sql loader) But we have pr
-
My Mother, over the weekend, managed to get her account locked after misstyping her email multiple times. This is not the first time this has happened, so she went through the process of trying to change her password, via getting an email sent to her
-
HT4623 i tried to update my phone and it doesn't work.
i tried to update my phone and it doesn't work. Tried restoring from DFU, and other things. I got error message 3194 and have also gotten "this device isn't eligible for the requested build" What do i try now?