Deterministic functions
Hello
I'm trying to figure out if there are any rules by which it is possible to determine in a given situation, how many calls will be made to a deterministic function given the same inputs. I've put together a very basic test and for 100 rows with 10 different values, I get 70 calls to the deterministic function and 100 to the non-deterministic one:
SQL> CREATE OR REPLACE PACKAGE pkg_Test_Deterministic
2 IS
3
4 FUNCTION f_Deterministic(a number)
5 RETURN NUMBER
6 DETERMINISTIC;
7
8 FUNCTION f_NonDeterministic(a number)
9 RETURN NUMBER;
10
11 PROCEDURE p_PrintCounts;
12
13 END;
14 /
Package created.
SQL> CREATE OR REPLACE PACKAGE BODY pkg_Test_Deterministic
2 IS
3 pn_DeterministicCount NUMBER;
4 pn_NonDeterministicCount NUMBER;
5
6
7 FUNCTION f_Deterministic(a number)
8 RETURN NUMBER
9 DETERMINISTIC
10 IS
11
12 BEGIN
13
14 IF pn_DeterministicCount IS NULL THEN
15
16 pn_DeterministicCount := 0;
17
18 END IF;
19
20 pn_DeterministicCount := pn_DeterministicCount + 1;
21
22 RETURN a;
23
24 END;
25
26
27 FUNCTION f_NonDeterministic(a number)
28 RETURN NUMBER
29 IS
30
31 BEGIN
32 IF pn_NonDeterministicCount IS NULL THEN
33
34 pn_NonDeterministicCount := 0;
35
36 END IF;
37
38 pn_NonDeterministicCount := pn_NonDeterministicCount + 1;
39
40 RETURN a;
41
42 END;
43
44 PROCEDURE p_PrintCounts
45 IS
46
47 BEGIN
48
49 dbms_output.put_line('Deterministic Count '||TO_CHAR(pn_DeterministicCount));
50 dbms_output.put_line('Non Deterministic Count '||TO_CHAR(pn_NonDeterministicCount));
51
52 pn_DeterministicCount := NULL;
53 pn_NonDeterministicCount := NULL;
54 END;
55
56 END;
57 /
Package body created.
SQL>
SQL> CREATE TABLE dt_test_ids AS
2 SELECT MOD(rownum,10) id FROM dual connect by level <= 100
3 /
Table created.
SQL> set serveroutput on
SQL> select
2 pkg_test_deterministic.f_Deterministic(id)
3 from
4 dt_test_ids;
PKG_TEST_DETERMINISTIC.F_DETERMINISTIC(ID)
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
100 rows selected.
SQL>
SQL> select
2 pkg_test_deterministic.f_NonDeterministic(id)
3 from
4 dt_test_ids;
PKG_TEST_DETERMINISTIC.F_NONDETERMINISTIC(ID)
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
100 rows selected.
SQL>
SQL> exec pkg_test_deterministic.p_PrintCounts;
Deterministic Count 70
Non Deterministic Count 100
SQL> select * from v$version;
BANNER
Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - Prod
PL/SQL Release 10.2.0.2.0 - Production
CORE 10.2.0.2.0 Production
TNS for 32-bit Windows: Version 10.2.0.2.0 - Production
NLSRTL Version 10.2.0.2.0 - ProductionI scaled it up and found that it held true for 1000 rows (i.e. 700 calls to the deterministic function) and I tried it with a package that had no variables (in case that was somehow affecting it. Finally I tried a stand alone function and outputted using dbms_output, and found the same result again. The only thing that appeared to alter the result slightly (69 calls rather than 70) was to pass MOD(rownum,10) as the parameter rather than the column.
This is more out of pure curiosity than anything. Is there a particular event that can be traced to see when oracle is deciding to make a call/cache a set of values???
Cheers
David
Hello
Thank's for the link. I had read it but I missed the last line in Johnathan Lewis' post stating that there doesn't appear to be any fixed rule. I was hoping to find out a way of determining what those rules are. Oh well.
Thanks anyway
David
Similar Messages
-
Oracle 11g function based columns - deterministic function or not?
Hi all, here is my situation:
I added function based column in my table and created index on this column.
I need this since in my ADF application, I need to be able to sort by this column.
The function (that this column is based on) I had to make it DETERMINISTIC (otherwise it can not be done).
So far so good.
My function is accepting 3 parameters (all NUMBERs) which are practically 3 primary keys from 3 different tables. Based on which key is present, my function is returning "Code" - column (VARCHAR2) from any of those 3 tables. And for sure "Code" can change in any of those table.
So my function is not really a DETERMINISTIC function.
-Should I update the function and make it nondeterministic? Will it still work? Will the index be valid if the function is nondeterministic?
-What is the consequence if it is not deterministic?
-If I leave i as deterministic - somehow the result is cached. Will my function always going to be re-executed for each row (having on mind it is not really deterministic)?
-Is there better solution than (function based column and index on it) in my case?
Thanks, VesnaOK, Damorgan, here are some more details:
Versin Numbers:
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
PL/SQL Release 11.1.0.7.0 - Production
TABLE:
alter table MY_VIRTUAL_COLUMN add dispatch_customer_name GENERATED ALWAYS AS (get_dispatch_customer_name(disloc_id, cus_id, cusloc_id)) VIRTUAL;
create index dispatch_customer_name_i on MY_VIRTUAL_COLUMN(dispatch_customer_name);FUNCTION:
CREATE OR REPLACE FUNCTION get_dispatch_customer_name(p_disloc_id NUMBER,
p_cus_id NUMBER,
p_cusloc_id NUMBER)
RETURN VARCHAR2 DETERMINISTIC IS
v_result VARCHAR2(1000) := NULL;
BEGIN
IF p_cus_id IS NULL THEN
IF p_cusloc_id IS NULL THEN
SELECT d.name
INTO v_result
FROM dispatch_locations d
WHERE d.disloc_id = p_disloc_id;
ELSE
SELECT l.name || ' (' || l.code || ')'
INTO v_result
FROM customer_locations l
WHERE l.cusloc_id = p_cusloc_id;
END IF;
ELSE
SELECT s.name || ' (' || s.code || ')'
INTO v_result
FROM customers s
WHERE s.cus_id = p_cus_id;
END IF;
RETURN v_result;
EXCEPTION
WHEN OTHERS THEN
RETURN NULL;
END get_dispatch_customer_name;Hope this will help
Thanks, Vesna -
What are deterministic functions in oracle.??
Hi,
Can anyone give me any information regarding deterministic functions?
ThanksI am not sure I understand what you are saying here. If you declare a function to be deterministic, then yes, Oracle may cache the results of the call and reuse the cached result when it sees another call to the function with the same parameters.
However, given that value is different in your third rowm, it appears that you may have two different function calls here.
Another thing to note is that you can declare any function to be deterministic, and Oracle will believe you. It does not make any attempt to decide whether you are correct or not.
SQL> CREATE FUNCTION determ (p_num IN NUMBER) RETURN NUMBER
2 DETERMINISTIC AS
3 BEGIN
4 RETURN p_num * DBMS_RANDOM.VALUE();
5 END;
6 /
Function created.
SQL> CREATE FUNCTION nondeterm (p_num IN NUMBER) RETURN NUMBER AS
2 BEGIN
3 RETURN p_num * DBMS_RANDOM.VALUE();
4 END;
5 /
Function created.
SQL> SELECT num, determ(num)
2 FROM (SELECT rownum num FROM all_objects
3 WHERE rownum <= 5
4 UNION ALL
5 SELECT rownum num FROM all_objects
6 WHERE rownum <= 5);
NUM DETERM(NUM)
1 .808346096
2 1.24224706
3 2.55670491
4 .814681413
5 3.10128137
1 .117673406
2 1.24224706
3 2.55670491
4 .814681413
5 3.10128137
10 rows selected.
SQL> SELECT num, nondeterm(num)
2 FROM (SELECT rownum num FROM all_objects
3 WHERE rownum <= 5
4 UNION ALL
5 SELECT rownum num FROM all_objects
6 WHERE rownum <= 5);
NUM NONDETERM(NUM)
1 .536325578
2 1.6236528
3 .628491757
4 2.6261965
5 4.09006466
1 .419011544
2 1.01745468
3 2.76301772
4 2.32793484
5 3.72438691So, the deterministic version did cache the function result (I'm not sure why it did not cache 1), but the non-deterministic version was called once for each row.
John -
Deterministic Functions don't work
I have created the following package in Oracle 9i:
CREATE OR REPLACE PACKAGE MyPackage IS
FUNCTION MyDetFunc RETURN NUMBER DETERMINISTIC;
END MyPackage;
CREATE OR REPLACE PACKAGE BODY MyPackage IS
i NUMBER := 0;
FUNCTION MyDetFunc RETURN NUMBER IS
BEGIN
i := i + 1;
RETURN i;
END;
END MyPackage;
wich defines a function not really deterministic, but selon the documentation it shouldnt matter.
Now I query a table with more than two rows.... And I get two different results!!!!!
Same results can be achieved if you display a message with dbms_output, you can see the function is called every time someone calls it ... Exactly the same way as if it wasn't deterministic.
I have done test with really deterministic functions
and i have never got any performance improvement.
Does anybody knows how this really works? Do you have any proof that deterministic functions work?
What about functions in PL/SQL like sysdate that are "read consistent"? How is it implemented?On the contrary, deterministic functions do work, but only if you use them properly. I presume you are complaining about behaviour like this...
SQL> SELECT MyPackage.MyDetFunc FROM t1;
MYDETFUNC
1
2
3
4
5
6
7
8
9
9 rows selected.
SQL> SELECT MyPackage.MyDetFunc FROM t1 ORDER BY col3;
MYDETFUNC
10
11
12
13
14
15
17
18
16
9 rows selected.
SQL> The documentation states qute clearly that the database has no well of telling whether a function you assert is DETERMINISTIC actually is deterministic. You have asserted the function is DETERMINISTIC when clearly it is not. The bad results are therefore your fault.
As for performance, well, DETERMINISTIC only affects function-based indexes. Check this out:
CREATE OR REPLACE PACKAGE MyPackage
IS
FUNCTION MyDetFunc (n IN NUMBER) RETURN NUMBER DETERMINISTIC;
END MyPackage;
CREATE OR REPLACE PACKAGE BODY MyPackage
IS
FUNCTION MyDetFunc (n IN NUMBER) RETURN NUMBER IS
i NUMBER;
BEGIN
i := n + 0;
RETURN i;
END MyDetFunc;
END MyPackage;
SQL> SELECT * FROM t_10k WHERE MyPackage.MyDetFunc(col1) = 333;
COL1
COL2
COL3
333
APC
01-JUL-04
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'T_10K'
SQL> CREATE INDEX i_10k ON t_10k(MyPackage.MyPackage(col1));
Index created.
SQL> exec dbms_stats.gather_table_stats(user, 'T_10K')
PL/SQL procedure successfully completed.
SQL> exec dbms_stats.gather_index_stats(user, 'I_10K')
PL/SQL procedure successfully completed.
SQL> ALTER SESSION SET query_rewrite_enabled=true;
Session altered.
SQL> ALTER SESSION SET query_rewrite_integrity=trusted;
Session altered.
SQL> SELECT * FROM t_10k WHERE MyPackage.MyDetFunc(col1) = 333;
COL1
COL2
COL3
333
APC
01-JUL-04
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=16)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T_10K' (Cost=2 Card=1 By
tes=16)
2 1 INDEX (RANGE SCAN) OF 'I_10K' (NON-UNIQUE) (Cost=1 Card=
1)
SQL> This time it used the index rather than doing a full table scan. That is a performance gain. Note that if I had used your original package definition the function would not have been deterministic and the result would have been wrong. This is not the database's fault: this is because your assertion was false.
Cheers, APC -
Simple question for deterministic functions
It is written in oracle documents about deterministic functions:
"Indicates that the function returns the same result value whenever it is called with the same values for its parameters."
I am wondering is it cached? or is it performing in run time?
for example when we execute a sql stement just one time and if we execute it again will the deterministic function performed?I am wondering is it cached? or is it performing in run time?
PL/SQL Subprograms
If result caching is enabled and the function was already called before with the same parameter value(s) (implying the result was cached) then the cached result gets returned (if still in the cache) without running the function code to compute the result.
Regards
Etbin -
How to define a parallel, deterministic pl/sql function in OWB 11.2?
Hi,
at my customer site, we are starting with the new development work after upgrading from OWB 10.2 to 11.2 and we can't find the configuration parameter to define a parallel and deterministic function within a new package. The "old" function dialog in 10.2 had some checkboxes for those two features ...
Thanks in advance
MichaelThanks for the advice, the Cut & Copy idea from MccM is working fine, however is not really a solution for the problem. But we are using it as a workaround for the moment.
Just for documentation: There already exists a bugfix, addressing the issue of lost parrallel and deterministic information during an upgrade from OWB10.2 to 11.2 (see bug 14673399 and patch 16082939)
And for at least some of us with access to Oracle Support: Our onsite Oracle consultant opened a service request for this issue: 3-6773545351 (You will not be able to see the request unless You are an Oracle employee, but maybe the reference is helpful for You.) -
Help optimizing query with function
Hello experts,
I need your help optmizing this query which has a condition that matches on results of non-deterministic function. The non-deterministic functino is fedtaxpk.fedtaxpk_pkg.GETFIELDDATAGROUPSEQKEY. Values that it returns depends on contents of a table, so I can't really create a function index.
Any input will be appreciated. Thanks in advance!
Sorry I couln't format the query plan properly. Can somebody advise how? Thanks again!
Giovanni
explain plan for
WITH tg AS
(SELECT taxgroup_code FROM taxgroup
WHERE taxgroup_code = 'TAXGROUP2' --?
AND taxgroup_delete_ind = 'N' AND taxgroup_active_ind = 'A'),
le_hb AS
(SELECT tgi.taxgroup_code, tgi.legalentity_id, tgi.hyperionbase_id, ou.orgunit_code, ou.hyperionbase_code
FROM tg, taxgroupitem tgi, orgunit_vw ou
WHERE tg.taxgroup_code = tgi.taxgroup_code
AND tgi.legalentity_id = ou.legalentity_id AND tgi.hyperionbase_id = ou.hyperionbase_id
UNION
SELECT tgi.taxgroup_code, tgi.legalentity_id, ou.hyperionbase_id, ou.orgunit_code, ou.hyperionbase_code
FROM tg, taxgroupitem tgi, orgunit_vw ou
WHERE tg.taxgroup_code = tgi.taxgroup_code
AND tgi.legalentity_id = ou.legalentity_id AND tgi.hyperionbase_id IS NULL),
au AS
(SELECT appusage_code FROM appusage WHERE appusage_code = 'CONSOLIDATION'),
prs AS
(SELECT prs_key,
(CASE WHEN instr(prs_key, ':') = 0 THEN prs_key
ELSE SUBSTR(prs_key, 1, (instr(prs_key, ':')-1) ) END) first_val
FROM
(SELECT fedtaxpk.fedtaxpk_pkg.GETFIELDDATAGROUPSEQKEY(164415 --?
) prs_key
FROM dual
grs AS
(SELECT prs.*, fd.fielddata_group_sequence fd_grpseq
FROM prs, fielddata fd, le_hb
WHERE prs.first_val = fd.fielddata_value
AND le_hb.legalentity_id = fd.legalentity_id
AND le_hb.hyperionbase_id = fd.hyperionbase_id),
fdk AS
(SELECT
cd.celldef_id, fedtaxpk.fedtaxpk_pkg.GETFIELDDATAGROUPSEQKEY(fd.fielddata_group_sequence) fd_key,
fd.fielddata_value fd_val, fd.fielddata_group_sequence fd_grpseq,
ROW_NUMBER() OVER (PARTITION BY cd.celldef_id, fedtaxpk.fedtaxpk_pkg.GETFIELDDATAGROUPSEQKEY(fd.fielddata_group_sequence)
ORDER BY fd.fielddata_group_sequence) rn,
grs.prs_key
FROM le_hb, grs, fielddata fd, tablecell tc, celldef cd, tabledef td, appusage au
WHERE le_hb.legalentity_id = fd.legalentity_id AND le_hb.hyperionbase_id = fd.hyperionbase_id
AND fd.fielddata_id = tc.fielddata_id AND tc.celldef_id = cd.celldef_id
AND cd.tabledef_id = td.tabledef_id
AND grs.fd_grpseq = fd.fielddata_parent_row_sequence
and grs.prs_key = fedtaxpk.fedtaxpk_pkg.GETFIELDDATAGROUPSEQKEY(fd.fielddata_parent_row_sequence)
AND cd.celldef_key_ind = 'Y'
AND fd.fielddata_delete_ind = 'N'
AND td.tabledef_id = 2265
fda AS
(SELECT
cd.celldef_id, fedtaxpk.fedtaxpk_pkg.GETFIELDDATAGROUPSEQKEY(fd.fielddata_group_sequence) fd_key,
TO_CHAR(TO_NUMBER(SUM(fd.fielddata_value))) fd_val,
MIN(fd.fielddata_group_sequence) fd_grpseq,
grs.prs_key
FROM le_hb, grs, fielddata fd, tablecell tc, celldef cd, tabledef td
WHERE le_hb.legalentity_id = fd.legalentity_id AND le_hb.hyperionbase_id = fd.hyperionbase_id
AND fd.fielddata_id = tc.fielddata_id AND tc.celldef_id = cd.celldef_id
AND cd.tabledef_id = td.tabledef_id
AND grs.fd_grpseq = fd.fielddata_parent_row_sequence
and grs.prs_key = fedtaxpk.fedtaxpk_pkg.GETFIELDDATAGROUPSEQKEY(fd.fielddata_parent_row_sequence)
AND cd.celldef_adjustable_ind = 'Y'
AND fd.fielddata_delete_ind = 'N'
AND td.tabledef_id = 2265
GROUP BY cd.celldef_id, fedtaxpk.fedtaxpk_pkg.GETFIELDDATAGROUPSEQKEY(fd.fielddata_group_sequence),
grs.prs_key
SELECT NULL LEGALENTITY_ID, NULL hyperionbase_id, fdk.celldef_id, TO_CHAR(NULL) role_code, NULL userinfo_id, cd.celldef_adjustable_ind,
'N' celldef_editable_ind, cd.celldef_filter_code, cd.celldef_validate_rule, cd.celldef_list_code,
cd.celldef_longstring_ind, aua.appusageaccess_visible_ind celldef_viewable_ind,
cd.celldef_column_sequence, cd.celldef_column_label,
cd.celldef_column_sort_order, NULL tablecell_id, fdk.fd_grpseq tablecell_row_sequence, NULL tablecell_row_label,
'N' tablecell_delete_ind, NULL tablecell_create_by, TO_DATE(NULL) tablecell_create_dt, TO_CHAR(NULL) tablecell_update_by,
TO_DATE(NULL) tablecell_update_dt, NULL fielddata_id, TO_CHAR(NULL) datatype_code, NULL fielddata_adjref_id,
fdk.fd_grpseq fielddata_group_sequence, NULL fielddata_parent_row_sequence, NULL lookup_id,
fdk.fd_val fielddata_value, 'N' fielddata_delete_ind, TO_CHAR(NULL) fielddata_create_by,
TO_DATE(NULL) fielddata_create_dt, TO_CHAR(NULL) fielddata_update_by, TO_DATE(NULL) fielddata_update_dt,
fdk.fd_key
FROM fdk, celldef cd, appusageaccess aua, au
WHERE fdk.celldef_id = cd.celldef_id
AND cd.celldef_id = aua.celldef_id
AND aua.appusage_code = au.appusage_code
AND fdk.rn = 1
UNION ALL
SELECT NULL LEGALENTITY_ID, NULL hyperionbase_id, fda.celldef_id, TO_CHAR(NULL) role_code, NULL userinfo_id, cd.celldef_adjustable_ind,
'N' celldef_editable_ind, cd.celldef_filter_code, cd.celldef_validate_rule, cd.celldef_list_code,
cd.celldef_longstring_ind, aua.appusageaccess_visible_ind celldef_viewable_ind,
cd.celldef_column_sequence, cd.celldef_column_label,
cd.celldef_column_sort_order, NULL tablecell_id, fda.fd_grpseq tablecell_row_sequence, NULL tablecell_row_label,
'N' tablecell_delete_ind, NULL tablecell_create_by, TO_DATE(NULL) tablecell_create_dt, TO_CHAR(NULL) tablecell_update_by,
TO_DATE(NULL) tablecell_update_dt, NULL fielddata_id, TO_CHAR(NULL) datatype_code, NULL fielddata_adjref_id,
fda.fd_grpseq fielddata_group_sequence, NULL fielddata_parent_row_sequence, NULL lookup_id,
fda.fd_val fielddata_value, 'N' fielddata_delete_ind, TO_CHAR(NULL) fielddata_create_by,
TO_DATE(NULL) fielddata_create_dt, TO_CHAR(NULL) fielddata_update_by, TO_DATE(NULL) fielddata_update_dt,
fda.fd_key
FROM fda, celldef cd, appusageaccess aua, au
WHERE fda.celldef_id = cd.celldef_id
AND cd.celldef_id = aua.celldef_id
AND aua.appusage_code = au.appusage_code
ORDER BY fielddata_group_sequence, celldef_column_sequence
Query Plan:
Plan hash value: 522363234
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 2 | 6227 | 249 (2)| 00:00:03 |
| 1 | TEMP TABLE TRANSFORMATION | | | | | |
| 2 | LOAD AS SELECT | | | | | |
|* 3 | TABLE ACCESS BY INDEX ROWID | TAXGROUP | 1 | 14 | 1 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN | PK_TAXGROUP | 1 | | 0 (0)| 00:00:01 |
| 5 | LOAD AS SELECT | | | | | |
| 6 | SORT UNIQUE | | 4 | 224 | 12 (59)| 00:00:01 |
| 7 | UNION-ALL | | | | | |
| 8 | TABLE ACCESS BY INDEX ROWID | ORGUNIT | 1 | 29 | 2 (0)| 00:00:01 |
| 9 | NESTED LOOPS | | 1 | 56 | 5 (0)| 00:00:01 |
| 10 | NESTED LOOPS | | 1 | 27 | 3 (0)| 00:00:01 |
| 11 | VIEW | | 1 | 10 | 2 (0)| 00:00:01 |
| 12 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B51_2EBE182 | 1 | 10 | 2 (0)| 00:00:01 |
|* 13 | TABLE ACCESS BY INDEX ROWID | TAXGROUPITEM | 1 | 17 | 1 (0)| 00:00:01 |
|* 14 | INDEX RANGE SCAN | XF1_TAXGROUPITEM_TAXGROUP | 1 | | 0 (0)| 00:00:01 |
|* 15 | INDEX RANGE SCAN | XF1_ORGUNIT_ID | 1 | | 1 (0)| 00:00:01 |
| 16 | TABLE ACCESS BY INDEX ROWID | ORGUNIT | 3 | 87 | 2 (0)| 00:00:01 |
| 17 | NESTED LOOPS | | 3 | 168 | 5 (0)| 00:00:01 |
| 18 | NESTED LOOPS | | 1 | 27 | 3 (0)| 00:00:01 |
| 19 | VIEW | | 1 | 10 | 2 (0)| 00:00:01 |
| 20 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B51_2EBE182 | 1 | 10 | 2 (0)| 00:00:01 |
|* 21 | TABLE ACCESS BY INDEX ROWID | TAXGROUPITEM | 1 | 17 | 1 (0)| 00:00:01 |
|* 22 | INDEX RANGE SCAN | XF1_TAXGROUPITEM_TAXGROUP | 1 | | 0 (0)| 00:00:01 |
|* 23 | INDEX RANGE SCAN | XF1_ORGUNIT_ID | 3 | | 1 (0)| 00:00:01 |
| 24 | LOAD AS SELECT | | | | | |
|* 25 | INDEX UNIQUE SCAN | PK_APPUSAGE | 1 | 10 | 0 (0)| 00:00:01 |
| 26 | LOAD AS SELECT | | | | | |
|* 27 | TABLE ACCESS BY INDEX ROWID | FIELDDATA | 7 | 147 | 28 (0)| 00:00:01 |
| 28 | NESTED LOOPS | | 27 | 1269 | 117 (1)| 00:00:02 |
| 29 | NESTED LOOPS | | 4 | 104 | 4 (0)| 00:00:01 |
| 30 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
| 31 | VIEW | | 4 | 104 | 2 (0)| 00:00:01 |
| 32 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B52_2EBE182 | 4 | 388 | 2 (0)| 00:00:01 |
|* 33 | INDEX RANGE SCAN | XF11_DATA_LE_HB | 117 | | 12 (0)| 00:00:01 |
| 34 | SORT ORDER BY | | 2 | 6227 | 248 (51)| 00:00:03 |
| 35 | UNION-ALL | | | | | |
| 36 | NESTED LOOPS | | 1 | 4110 | 125 (2)| 00:00:02 |
| 37 | MERGE JOIN CARTESIAN | | 1 | 4093 | 124 (2)| 00:00:02 |
| 38 | NESTED LOOPS | | 1 | 4076 | 122 (2)| 00:00:02 |
|* 39 | VIEW | | 1 | 4043 | 121 (2)| 00:00:02 |
|* 40 | WINDOW SORT PUSHED RANK | | 1 | 2099 | 121 (2)| 00:00:02 |
| 41 | MERGE JOIN CARTESIAN | | 1 | 2099 | 120 (1)| 00:00:02 |
| 42 | NESTED LOOPS | | 1 | 2099 | 119 (1)| 00:00:02 |
| 43 | NESTED LOOPS | | 1 | 2088 | 118 (1)| 00:00:02 |
|* 44 | HASH JOIN | | 1 | 2077 | 117 (1)| 00:00:02 |
|* 45 | TABLE ACCESS BY INDEX ROWID| FIELDDATA | 117 | 3744 | 28 (0)| 00:00:01 |
| 46 | NESTED LOOPS | | 466 | 28892 | 114 (0)| 00:00:02 |
| 47 | NESTED LOOPS | | 4 | 120 | 2 (0)| 00:00:01 |
|* 48 | INDEX UNIQUE SCAN | PK_TABLEDEF | 1 | 4 | 0 (0)| 00:00:01 |
| 49 | VIEW | | 4 | 104 | 2 (0)| 00:00:01 |
| 50 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B52_2EBE182 | 4 | 388 | 2 (0)| 00:00:01 |
|* 51 | INDEX RANGE SCAN | XF11_DATA_LE_HB | 117 | | 12 (0)| 00:00:01 |
| 52 | VIEW | | 27 | 54405 | 2 (0)| 00:00:01 |
| 53 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B54_2EBE182 | 27 | 1269 | 2 (0)| 00:00:01 |
| 54 | TABLE ACCESS BY INDEX ROWID | TABLECELL | 1 | 11 | 1 (0)| 00:00:01 |
|* 55 | INDEX UNIQUE SCAN | XF1_TBLCEL_DATA | 1 | | 0 (0)| 00:00:01 |
|* 56 | TABLE ACCESS BY INDEX ROWID | CELLDEF | 1 | 11 | 1 (0)| 00:00:01 |
|* 57 | INDEX UNIQUE SCAN | PK_CELLDEF | 1 | | 0 (0)| 00:00:01 |
| 58 | BUFFER SORT | | 5 | | 120 (2)| 00:00:02 |
| 59 | INDEX FULL SCAN | PK_APPUSAGE | 5 | | 1 (0)| 00:00:01 |
| 60 | TABLE ACCESS BY INDEX ROWID | CELLDEF | 1 | 33 | 1 (0)| 00:00:01 |
|* 61 | INDEX UNIQUE SCAN | PK_CELLDEF | 1 | | 0 (0)| 00:00:01 |
| 62 | BUFFER SORT | | 1 | 17 | 123 (2)| 00:00:02 |
| 63 | VIEW | | 1 | 17 | 2 (0)| 00:00:01 |
| 64 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B53_2EBE182 | 1 | 10 | 2 (0)| 00:00:01 |
| 65 | TABLE ACCESS BY INDEX ROWID | APPUSAGEACCESS | 1 | 17 | 1 (0)| 00:00:01 |
|* 66 | INDEX UNIQUE SCAN | AK_APPUSAGEACCESS | 1 | | 0 (0)| 00:00:01 |
| 67 | NESTED LOOPS | | 1 | 2117 | 124 (2)| 00:00:02 |
| 68 | MERGE JOIN CARTESIAN | | 1 | 2100 | 123 (2)| 00:00:02 |
| 69 | NESTED LOOPS | | 1 | 2083 | 121 (2)| 00:00:02 |
| 70 | VIEW | | 1 | 2050 | 120 (2)| 00:00:02 |
| 71 | HASH GROUP BY | | 1 | 2091 | 120 (2)| 00:00:02 |
| 72 | NESTED LOOPS | | 1 | 2091 | 119 (1)| 00:00:02 |
| 73 | NESTED LOOPS | | 1 | 2080 | 118 (1)| 00:00:02 |
|* 74 | HASH JOIN | | 1 | 2069 | 117 (1)| 00:00:02 |
|* 75 | TABLE ACCESS BY INDEX ROWID | FIELDDATA | 117 | 3744 | 28 (0)| 00:00:01 |
| 76 | NESTED LOOPS | | 466 | 28892 | 114 (0)| 00:00:02 |
| 77 | NESTED LOOPS | | 4 | 120 | 2 (0)| 00:00:01 |
|* 78 | INDEX UNIQUE SCAN | PK_TABLEDEF | 1 | 4 | 0 (0)| 00:00:01 |
| 79 | VIEW | | 4 | 104 | 2 (0)| 00:00:01 |
| 80 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B52_2EBE182 | 4 | 388 | 2 (0)| 00:00:01 |
|* 81 | INDEX RANGE SCAN | XF11_DATA_LE_HB | 117 | | 12 (0)| 00:00:01 |
| 82 | VIEW | | 27 | 54189 | 2 (0)| 00:00:01 |
| 83 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B54_2EBE182 | 27 | 1269 | 2 (0)| 00:00:01 |
| 84 | TABLE ACCESS BY INDEX ROWID | TABLECELL | 1 | 11 | 1 (0)| 00:00:01 |
|* 85 | INDEX UNIQUE SCAN | XF1_TBLCEL_DATA | 1 | | 0 (0)| 00:00:01 |
|* 86 | TABLE ACCESS BY INDEX ROWID | CELLDEF | 1 | 11 | 1 (0)| 00:00:01 |
|* 87 | INDEX UNIQUE SCAN | PK_CELLDEF | 1 | | 0 (0)| 00:00:01 |
| 88 | TABLE ACCESS BY INDEX ROWID | CELLDEF | 1 | 33 | 1 (0)| 00:00:01 |
|* 89 | INDEX UNIQUE SCAN | PK_CELLDEF | 1 | | 0 (0)| 00:00:01 |
| 90 | BUFFER SORT | | 1 | 17 | 122 (2)| 00:00:02 |
| 91 | VIEW | | 1 | 17 | 2 (0)| 00:00:01 |
| 92 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B53_2EBE182 | 1 | 10 | 2 (0)| 00:00:01 |
| 93 | TABLE ACCESS BY INDEX ROWID | APPUSAGEACCESS | 1 | 17 | 1 (0)| 00:00:01 |
|* 94 | INDEX UNIQUE SCAN | AK_APPUSAGEACCESS | 1 | | 0 (0)| 00:00:01 |
Predicate Information (identified by operation id):
3 - filter("TAXGROUP_DELETE_IND"='N' AND "TAXGROUP_ACTIVE_IND"='A')
4 - access("TAXGROUP_CODE"='TAXGROUP2')
13 - filter("TGI"."HYPERIONBASE_ID" IS NOT NULL)
14 - access("TG"."TAXGROUP_CODE"="TGI"."TAXGROUP_CODE")
15 - access("TGI"."LEGALENTITY_ID"="OU"."ORGUNIT_ID" AND "TGI"."HYPERIONBASE_ID"="OU"."HYPERIONBASE_ID")
21 - filter("TGI"."HYPERIONBASE_ID" IS NULL)
22 - access("TG"."TAXGROUP_CODE"="TGI"."TAXGROUP_CODE")
23 - access("TGI"."LEGALENTITY_ID"="OU"."ORGUNIT_ID")
25 - access("APPUSAGE_CODE"='CONSOLIDATION')
27 - filter("FD"."FIELDDATA_VALUE"=CASE INSTR("FEDTAXPK_PKG"."GETFIELDDATAGROUPSEQKEY"(164415),':') WHEN 0
THEN "FEDTAXPK_PKG"."GETFIELDDATAGROUPSEQKEY"(164415) ELSE
SUBSTR("FEDTAXPK_PKG"."GETFIELDDATAGROUPSEQKEY"(164415),1,INSTR("FEDTAXPK_PKG"."GETFIELDDATAGROUPSEQKEY"(16441
5),':')-1) END )
33 - access("LE_HB"."LEGALENTITY_ID"="FD"."LEGALENTITY_ID" AND
"LE_HB"."HYPERIONBASE_ID"="FD"."HYPERIONBASE_ID")
39 - filter("FDK"."RN"=1)
40 - filter(ROW_NUMBER() OVER ( PARTITION BY "CD"."CELLDEF_ID","FEDTAXPK_PKG"."GETFIELDDATAGROUPSEQKEY"("FD"
."FIELDDATA_GROUP_SEQUENCE") ORDER BY "FD"."FIELDDATA_GROUP_SEQUENCE")<=1)
44 - access("GRS"."FD_GRPSEQ"="FD"."FIELDDATA_PARENT_ROW_SEQUENCE" AND
"GRS"."PRS_KEY"="FEDTAXPK_PKG"."GETFIELDDATAGROUPSEQKEY"("FD"."FIELDDATA_PARENT_ROW_SEQUENCE"))
45 - filter("FD"."FIELDDATA_DELETE_IND"='N')
48 - access("TD"."TABLEDEF_ID"=2265)
51 - access("LE_HB"."LEGALENTITY_ID"="FD"."LEGALENTITY_ID" AND
"LE_HB"."HYPERIONBASE_ID"="FD"."HYPERIONBASE_ID")
55 - access("FD"."FIELDDATA_ID"="TC"."FIELDDATA_ID")
56 - filter("CD"."TABLEDEF_ID"=2265 AND "CD"."CELLDEF_KEY_IND"='Y')
57 - access("TC"."CELLDEF_ID"="CD"."CELLDEF_ID")
61 - access("FDK"."CELLDEF_ID"="CD"."CELLDEF_ID")
66 - access("AUA"."APPUSAGE_CODE"="AU"."APPUSAGE_CODE" AND "CD"."CELLDEF_ID"="AUA"."CELLDEF_ID")
74 - access("GRS"."FD_GRPSEQ"="FD"."FIELDDATA_PARENT_ROW_SEQUENCE" AND
"GRS"."PRS_KEY"="FEDTAXPK_PKG"."GETFIELDDATAGROUPSEQKEY"("FD"."FIELDDATA_PARENT_ROW_SEQUENCE"))
75 - filter("FD"."FIELDDATA_DELETE_IND"='N')
78 - access("TD"."TABLEDEF_ID"=2265)
81 - access("LE_HB"."LEGALENTITY_ID"="FD"."LEGALENTITY_ID" AND
"LE_HB"."HYPERIONBASE_ID"="FD"."HYPERIONBASE_ID")
85 - access("FD"."FIELDDATA_ID"="TC"."FIELDDATA_ID")
86 - filter("CD"."TABLEDEF_ID"=2265 AND "CD"."CELLDEF_ADJUSTABLE_IND"='Y')
87 - access("TC"."CELLDEF_ID"="CD"."CELLDEF_ID")
89 - access("FDA"."CELLDEF_ID"="CD"."CELLDEF_ID")
94 - access("AUA"."APPUSAGE_CODE"="AU"."APPUSAGE_CODE" AND "CD"."CELLDEF_ID"="AUA"."CELLDEF_ID")Thanks cd.
Here's the query plan:
Query Plan:
Plan hash value: 522363234
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 2 | 6227 | 249 (2)| 00:00:03 |
| 1 | TEMP TABLE TRANSFORMATION | | | | | |
| 2 | LOAD AS SELECT | | | | | |
|* 3 | TABLE ACCESS BY INDEX ROWID | TAXGROUP | 1 | 14 | 1 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN | PK_TAXGROUP | 1 | | 0 (0)| 00:00:01 |
| 5 | LOAD AS SELECT | | | | | |
| 6 | SORT UNIQUE | | 4 | 224 | 12 (59)| 00:00:01 |
| 7 | UNION-ALL | | | | | |
| 8 | TABLE ACCESS BY INDEX ROWID | ORGUNIT | 1 | 29 | 2 (0)| 00:00:01 |
| 9 | NESTED LOOPS | | 1 | 56 | 5 (0)| 00:00:01 |
| 10 | NESTED LOOPS | | 1 | 27 | 3 (0)| 00:00:01 |
| 11 | VIEW | | 1 | 10 | 2 (0)| 00:00:01 |
| 12 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B51_2EBE182 | 1 | 10 | 2 (0)| 00:00:01 |
|* 13 | TABLE ACCESS BY INDEX ROWID | TAXGROUPITEM | 1 | 17 | 1 (0)| 00:00:01 |
|* 14 | INDEX RANGE SCAN | XF1_TAXGROUPITEM_TAXGROUP | 1 | | 0 (0)| 00:00:01 |
|* 15 | INDEX RANGE SCAN | XF1_ORGUNIT_ID | 1 | | 1 (0)| 00:00:01 |
| 16 | TABLE ACCESS BY INDEX ROWID | ORGUNIT | 3 | 87 | 2 (0)| 00:00:01 |
| 17 | NESTED LOOPS | | 3 | 168 | 5 (0)| 00:00:01 |
| 18 | NESTED LOOPS | | 1 | 27 | 3 (0)| 00:00:01 |
| 19 | VIEW | | 1 | 10 | 2 (0)| 00:00:01 |
| 20 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B51_2EBE182 | 1 | 10 | 2 (0)| 00:00:01 |
|* 21 | TABLE ACCESS BY INDEX ROWID | TAXGROUPITEM | 1 | 17 | 1 (0)| 00:00:01 |
|* 22 | INDEX RANGE SCAN | XF1_TAXGROUPITEM_TAXGROUP | 1 | | 0 (0)| 00:00:01 |
|* 23 | INDEX RANGE SCAN | XF1_ORGUNIT_ID | 3 | | 1 (0)| 00:00:01 |
| 24 | LOAD AS SELECT | | | | | |
|* 25 | INDEX UNIQUE SCAN | PK_APPUSAGE | 1 | 10 | 0 (0)| 00:00:01 |
| 26 | LOAD AS SELECT | | | | | |
|* 27 | TABLE ACCESS BY INDEX ROWID | FIELDDATA | 7 | 147 | 28 (0)| 00:00:01 |
| 28 | NESTED LOOPS | | 27 | 1269 | 117 (1)| 00:00:02 |
| 29 | NESTED LOOPS | | 4 | 104 | 4 (0)| 00:00:01 |
| 30 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
| 31 | VIEW | | 4 | 104 | 2 (0)| 00:00:01 |
| 32 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B52_2EBE182 | 4 | 388 | 2 (0)| 00:00:01 |
|* 33 | INDEX RANGE SCAN | XF11_DATA_LE_HB | 117 | | 12 (0)| 00:00:01 |
| 34 | SORT ORDER BY | | 2 | 6227 | 248 (51)| 00:00:03 |
| 35 | UNION-ALL | | | | | |
| 36 | NESTED LOOPS | | 1 | 4110 | 125 (2)| 00:00:02 |
| 37 | MERGE JOIN CARTESIAN | | 1 | 4093 | 124 (2)| 00:00:02 |
| 38 | NESTED LOOPS | | 1 | 4076 | 122 (2)| 00:00:02 |
|* 39 | VIEW | | 1 | 4043 | 121 (2)| 00:00:02 |
|* 40 | WINDOW SORT PUSHED RANK | | 1 | 2099 | 121 (2)| 00:00:02 |
| 41 | MERGE JOIN CARTESIAN | | 1 | 2099 | 120 (1)| 00:00:02 |
| 42 | NESTED LOOPS | | 1 | 2099 | 119 (1)| 00:00:02 |
| 43 | NESTED LOOPS | | 1 | 2088 | 118 (1)| 00:00:02 |
|* 44 | HASH JOIN | | 1 | 2077 | 117 (1)| 00:00:02 |
|* 45 | TABLE ACCESS BY INDEX ROWID| FIELDDATA | 117 | 3744 | 28 (0)| 00:00:01 |
| 46 | NESTED LOOPS | | 466 | 28892 | 114 (0)| 00:00:02 |
| 47 | NESTED LOOPS | | 4 | 120 | 2 (0)| 00:00:01 |
|* 48 | INDEX UNIQUE SCAN | PK_TABLEDEF | 1 | 4 | 0 (0)| 00:00:01 |
| 49 | VIEW | | 4 | 104 | 2 (0)| 00:00:01 |
| 50 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B52_2EBE182 | 4 | 388 | 2 (0)| 00:00:01 |
|* 51 | INDEX RANGE SCAN | XF11_DATA_LE_HB | 117 | | 12 (0)| 00:00:01 |
| 52 | VIEW | | 27 | 54405 | 2 (0)| 00:00:01 |
| 53 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B54_2EBE182 | 27 | 1269 | 2 (0)| 00:00:01 |
| 54 | TABLE ACCESS BY INDEX ROWID | TABLECELL | 1 | 11 | 1 (0)| 00:00:01 |
|* 55 | INDEX UNIQUE SCAN | XF1_TBLCEL_DATA | 1 | | 0 (0)| 00:00:01 |
|* 56 | TABLE ACCESS BY INDEX ROWID | CELLDEF | 1 | 11 | 1 (0)| 00:00:01 |
|* 57 | INDEX UNIQUE SCAN | PK_CELLDEF | 1 | | 0 (0)| 00:00:01 |
| 58 | BUFFER SORT | | 5 | | 120 (2)| 00:00:02 |
| 59 | INDEX FULL SCAN | PK_APPUSAGE | 5 | | 1 (0)| 00:00:01 |
| 60 | TABLE ACCESS BY INDEX ROWID | CELLDEF | 1 | 33 | 1 (0)| 00:00:01 |
|* 61 | INDEX UNIQUE SCAN | PK_CELLDEF | 1 | | 0 (0)| 00:00:01 |
| 62 | BUFFER SORT | | 1 | 17 | 123 (2)| 00:00:02 |
| 63 | VIEW | | 1 | 17 | 2 (0)| 00:00:01 |
| 64 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B53_2EBE182 | 1 | 10 | 2 (0)| 00:00:01 |
| 65 | TABLE ACCESS BY INDEX ROWID | APPUSAGEACCESS | 1 | 17 | 1 (0)| 00:00:01 |
|* 66 | INDEX UNIQUE SCAN | AK_APPUSAGEACCESS | 1 | | 0 (0)| 00:00:01 |
| 67 | NESTED LOOPS | | 1 | 2117 | 124 (2)| 00:00:02 |
| 68 | MERGE JOIN CARTESIAN | | 1 | 2100 | 123 (2)| 00:00:02 |
| 69 | NESTED LOOPS | | 1 | 2083 | 121 (2)| 00:00:02 |
| 70 | VIEW | | 1 | 2050 | 120 (2)| 00:00:02 |
| 71 | HASH GROUP BY | | 1 | 2091 | 120 (2)| 00:00:02 |
| 72 | NESTED LOOPS | | 1 | 2091 | 119 (1)| 00:00:02 |
| 73 | NESTED LOOPS | | 1 | 2080 | 118 (1)| 00:00:02 |
|* 74 | HASH JOIN | | 1 | 2069 | 117 (1)| 00:00:02 |
|* 75 | TABLE ACCESS BY INDEX ROWID | FIELDDATA | 117 | 3744 | 28 (0)| 00:00:01 |
| 76 | NESTED LOOPS | | 466 | 28892 | 114 (0)| 00:00:02 |
| 77 | NESTED LOOPS | | 4 | 120 | 2 (0)| 00:00:01 |
|* 78 | INDEX UNIQUE SCAN | PK_TABLEDEF | 1 | 4 | 0 (0)| 00:00:01 |
| 79 | VIEW | | 4 | 104 | 2 (0)| 00:00:01 |
| 80 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B52_2EBE182 | 4 | 388 | 2 (0)| 00:00:01 |
|* 81 | INDEX RANGE SCAN | XF11_DATA_LE_HB | 117 | | 12 (0)| 00:00:01 |
| 82 | VIEW | | 27 | 54189 | 2 (0)| 00:00:01 |
| 83 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B54_2EBE182 | 27 | 1269 | 2 (0)| 00:00:01 |
| 84 | TABLE ACCESS BY INDEX ROWID | TABLECELL | 1 | 11 | 1 (0)| 00:00:01 |
|* 85 | INDEX UNIQUE SCAN | XF1_TBLCEL_DATA | 1 | | 0 (0)| 00:00:01 |
|* 86 | TABLE ACCESS BY INDEX ROWID | CELLDEF | 1 | 11 | 1 (0)| 00:00:01 |
|* 87 | INDEX UNIQUE SCAN | PK_CELLDEF | 1 | | 0 (0)| 00:00:01 |
| 88 | TABLE ACCESS BY INDEX ROWID | CELLDEF | 1 | 33 | 1 (0)| 00:00:01 |
|* 89 | INDEX UNIQUE SCAN | PK_CELLDEF | 1 | | 0 (0)| 00:00:01 |
| 90 | BUFFER SORT | | 1 | 17 | 122 (2)| 00:00:02 |
| 91 | VIEW | | 1 | 17 | 2 (0)| 00:00:01 |
| 92 | TABLE ACCESS FULL | SYS_TEMP_0FD9D9B53_2EBE182 | 1 | 10 | 2 (0)| 00:00:01 |
| 93 | TABLE ACCESS BY INDEX ROWID | APPUSAGEACCESS | 1 | 17 | 1 (0)| 00:00:01 |
|* 94 | INDEX UNIQUE SCAN | AK_APPUSAGEACCESS | 1 | | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id):
3 - filter("TAXGROUP_DELETE_IND"='N' AND "TAXGROUP_ACTIVE_IND"='A')
4 - access("TAXGROUP_CODE"='TAXGROUP2')
13 - filter("TGI"."HYPERIONBASE_ID" IS NOT NULL)
14 - access("TG"."TAXGROUP_CODE"="TGI"."TAXGROUP_CODE")
15 - access("TGI"."LEGALENTITY_ID"="OU"."ORGUNIT_ID" AND "TGI"."HYPERIONBASE_ID"="OU"."HYPERIONBASE_ID")
21 - filter("TGI"."HYPERIONBASE_ID" IS NULL)
22 - access("TG"."TAXGROUP_CODE"="TGI"."TAXGROUP_CODE")
23 - access("TGI"."LEGALENTITY_ID"="OU"."ORGUNIT_ID")
25 - access("APPUSAGE_CODE"='CONSOLIDATION')
27 - filter("FD"."FIELDDATA_VALUE"=CASE INSTR("FEDTAXPK_PKG"."GETFIELDDATAGROUPSEQKEY"(164415),':') WHEN 0
THEN "FEDTAXPK_PKG"."GETFIELDDATAGROUPSEQKEY"(164415) ELSE
SUBSTR("FEDTAXPK_PKG"."GETFIELDDATAGROUPSEQKEY"(164415),1,INSTR("FEDTAXPK_PKG"."GETFIELDDATAGROUPSEQKEY"(16441
5),':')-1) END )
33 - access("LE_HB"."LEGALENTITY_ID"="FD"."LEGALENTITY_ID" AND
"LE_HB"."HYPERIONBASE_ID"="FD"."HYPERIONBASE_ID")
39 - filter("FDK"."RN"=1)
40 - filter(ROW_NUMBER() OVER ( PARTITION BY "CD"."CELLDEF_ID","FEDTAXPK_PKG"."GETFIELDDATAGROUPSEQKEY"("FD"
."FIELDDATA_GROUP_SEQUENCE") ORDER BY "FD"."FIELDDATA_GROUP_SEQUENCE")<=1)
44 - access("GRS"."FD_GRPSEQ"="FD"."FIELDDATA_PARENT_ROW_SEQUENCE" AND
"GRS"."PRS_KEY"="FEDTAXPK_PKG"."GETFIELDDATAGROUPSEQKEY"("FD"."FIELDDATA_PARENT_ROW_SEQUENCE"))
45 - filter("FD"."FIELDDATA_DELETE_IND"='N')
48 - access("TD"."TABLEDEF_ID"=2265)
51 - access("LE_HB"."LEGALENTITY_ID"="FD"."LEGALENTITY_ID" AND
"LE_HB"."HYPERIONBASE_ID"="FD"."HYPERIONBASE_ID")
55 - access("FD"."FIELDDATA_ID"="TC"."FIELDDATA_ID")
56 - filter("CD"."TABLEDEF_ID"=2265 AND "CD"."CELLDEF_KEY_IND"='Y')
57 - access("TC"."CELLDEF_ID"="CD"."CELLDEF_ID")
61 - access("FDK"."CELLDEF_ID"="CD"."CELLDEF_ID")
66 - access("AUA"."APPUSAGE_CODE"="AU"."APPUSAGE_CODE" AND "CD"."CELLDEF_ID"="AUA"."CELLDEF_ID")
74 - access("GRS"."FD_GRPSEQ"="FD"."FIELDDATA_PARENT_ROW_SEQUENCE" AND
"GRS"."PRS_KEY"="FEDTAXPK_PKG"."GETFIELDDATAGROUPSEQKEY"("FD"."FIELDDATA_PARENT_ROW_SEQUENCE"))
75 - filter("FD"."FIELDDATA_DELETE_IND"='N')
78 - access("TD"."TABLEDEF_ID"=2265)
81 - access("LE_HB"."LEGALENTITY_ID"="FD"."LEGALENTITY_ID" AND
"LE_HB"."HYPERIONBASE_ID"="FD"."HYPERIONBASE_ID")
85 - access("FD"."FIELDDATA_ID"="TC"."FIELDDATA_ID")
86 - filter("CD"."TABLEDEF_ID"=2265 AND "CD"."CELLDEF_ADJUSTABLE_IND"='Y')
87 - access("TC"."CELLDEF_ID"="CD"."CELLDEF_ID")
89 - access("FDA"."CELLDEF_ID"="CD"."CELLDEF_ID")
94 - access("AUA"."APPUSAGE_CODE"="AU"."APPUSAGE_CODE" AND "CD"."CELLDEF_ID"="AUA"."CELLDEF_ID") -
Create, Update & Save Functions
Hi All,
This is my code for the requirement to print sales order in ALV Grid Format using OOPS concept.
Please tell me how i should add select button to the ALV Grid in the first column.
Also when i click on CREATE button a new blank line should be added to the alv grid.
when i click on UPDATE button the selected row should become editable & when i click on save then my Ztable should be update with the new values and all the changes made.
The Ztable has fields as of the IT_FIANL table.
I have gone through many links regarding this topic but cant implement it in my code.
REPORT z12darp_shad_so_alv_oops
MESSAGE-ID z12darp1.
*Class definition for handling double click
CLASS event_class DEFINITION DEFERRED.
*Class definition for ALV toolbar
CLASS lcl_alv_toolbar DEFINITION DEFERRED.
*AUTHOR: Darpana. Ahire
*DATE: 28/11/2008
*DESCRIPTION: To printsales order as Interactive ALV using OOPS concept.
*& D A T A D E C L R A T I O N
type-pools: icon.
INCLUDE z12darp_alv_oops.
data: ok_code_2008 like sy-ucomm.
*& Include Z12DARP_ALV_OOPS
*Author: Darpana. Ahire
*Date: 28/11/2008
*Description: ALV Grid Using OOPS concept.
tables: z12Darp_final.
types: begin of ty_vbak,
vbeln type vbeln_va,
erdat type erdat,
vkorg type vkorg,
spart type spart,
end of ty_vbak.
types: begin of ty_vbap,
vbeln type vbeln_va,
posnr type posnr_va,
matnr type matnr,
netpr type netpr,
netwr type netwr_ap,
end of ty_vbap.
types: begin of ty_final,
vbeln type vbeln_va,
erdat type erdat,
vkorg type vkorg,
spart type spart,
posnr type posnr_va,
matnr type matnr,
netpr type netpr,
netwr type netwr_ap,
end of ty_final.
data: wa_vbak type ty_vbak,
wa_vbap type ty_vbap,
wa_final type ty_final.
data: it_vbak type standard table of ty_vbak,
it_vbap type standard table of ty_vbap,
it_final type standard table of ty_final.
data: v_vbeln type vbeln_va.
data: cust type ref to cl_gui_custom_container,
alv type ref to cl_gui_alv_grid,
event_receiver TYPE REF TO event_class.
data: wa_fcat type lvc_s_fcat,
it_fcat type lvc_t_fcat,
wa_layout type lvc_s_layo.
*Declaration for toolbar buttons
DATA : ty_toolbar TYPE stb_button.
data: c_alv_toolbar TYPE REF TO lcl_alv_toolbar. "Alv toolbar
*& S E L E C T I O N S C R E E N
SELECT-OPTIONS: ss_vbeln FOR v_vbeln.
*& I N I T I A L I Z A T I O N
INITIALIZATION.
PERFORM initial.
*& A T S E L E C T I O N - S C R E E N
AT SELECTION-SCREEN.
PERFORM at_sel_scr.
*& S T A R T - O F - S E L E C T I O N
START-OF-SELECTION.
PERFORM sel_records.
PERFORM join_tables.
PERFORM alv_output.
* CLASS lcl_event_receiver DEFINITION
CLASS event_class DEFINITION.
*Handling double click
PUBLIC SECTION.
METHODS:
handle_double_click
FOR EVENT double_click OF cl_gui_alv_grid
IMPORTING e_row e_column.
ENDCLASS. "lcl_event_receiver DEFINITION
* CLASS lcl_event_receiver IMPLEMENTATION
CLASS event_class IMPLEMENTATION.
METHOD handle_double_click.
case e_column.
when 'MATNR'.
read table it_final into wa_final index e_row-index.
set parameter id 'MAT' field wa_final-matnr.
call transaction 'MM03' and skip first screen.
endcase.
ENDMETHOD. "handle_double_click
endclass.
* CLASS lcl_alv_toolbar DEFINITION
* ALV event handler
CLASS lcl_alv_toolbar DEFINITION.
PUBLIC SECTION.
*Event for toolbar
on_toolbar
FOR EVENT toolbar
OF cl_gui_alv_grid
IMPORTING e_object e_interactive,
handle_user_command
for event user_command of cl_gui_alv_grid
importing e_ucomm.
endclass.
* CLASS lcl_alv_toolbar IMPLEMENTATION
* ALV event handler
CLASS lcl_alv_toolbar IMPLEMENTATION.
METHOD on_toolbar.
* Add customized toolbar buttons.
* variable for Toolbar Button
clear ty_toolbar.
ty_toolbar-icon = icon_create.
ty_toolbar-butn_type = 0.
ty_toolbar-text = 'CREATE'.
APPEND ty_toolbar TO e_object->mt_toolbar.
clear ty_toolbar.
ty_toolbar-icon = icon_change.
ty_toolbar-butn_type = 0.
ty_toolbar-text = 'UPDATE'.
APPEND ty_toolbar TO e_object->mt_toolbar.
clear ty_toolbar.
ty_toolbar-icon = icon_system_save.
ty_toolbar-butn_type = 0.
ty_toolbar-text = 'SAVE'.
APPEND ty_toolbar TO e_object->mt_toolbar.
ENDMETHOD. "on_toolbar
method handle_user_command.
case e_ucomm.
when 'CREATE'.
when 'UPDATE'.
endcase.
endmethod. "handle_user_command
ENDCLASS. "lcl_event_receiver IMPLEMENTATION
*& Module STATUS_2008 OUTPUT
* text
MODULE status_2008 OUTPUT.
SET PF-STATUS 'MENU1'.
SET TITLEBAR 'TITLE1'.
ENDMODULE. " STATUS_2008 OUTPUT
*& Module alv_display OUTPUT
* text
MODULE alv_display OUTPUT.
IF cust IS INITIAL.
* Creating object of container
CREATE OBJECT cust
EXPORTING
container_name = 'CUSTOM'.
* Creating object of alv
CREATE OBJECT alv
EXPORTING
i_parent = cust.
** create ALV event handler
* CREATE OBJECT c_alv_toolbar
* EXPORTING
* io_alv_grid = alv.
create object c_alv_toolbar.
* Register event handler
SET HANDLER c_alv_toolbar->on_toolbar FOR alv.
set handler c_alv_toolbar->handle_user_command for alv.
* alv layout
PERFORM alv_layout.
* alv field catalogue
PERFORM fieldcatalog_display.
* Displaying the ALV grid
CALL METHOD alv->set_table_for_first_display(
EXPORTING
is_layout = wa_layout
CHANGING
it_outtab = it_final
it_fieldcatalog = it_fcat ).
*Create object of the event class and setting handler for double click
CREATE OBJECT event_receiver.
SET HANDLER event_receiver->handle_double_click FOR alv.
ENDIF.
ENDMODULE. " alv_display OUTPUT
*& Module USER_COMMAND_2008 INPUT
* text
module USER_COMMAND_2008 input.
case ok_code_2008.
when 'EXT'.
leave program.
when 'BCK'.
leave to screen 0.
when 'UP'.
leave program.
endcase.
endmodule. " USER_COMMAND_2008 INPUT
*& E N D O F M A I N P R O G R A M
*& Form initial
* text
* --> p1 text
* <-- p2 text
FORM initial .
CLEAR: wa_vbak,
wa_vbap,
wa_final.
REFRESH: it_vbak,
it_vbap,
it_final.
ENDFORM. " initial
*& Form at_sel_scr
* text
* --> p1 text
* <-- p2 text
FORM at_sel_scr .
SELECT vbeln
INTO TABLE it_vbak
FROM vbak
WHERE vbeln IN ss_vbeln.
IF sy-subrc <> 0.
MESSAGE e000.
ENDIF.
ENDFORM. " at_sel_scr
*& Form sel_records
* text
* --> p1 text
* <-- p2 text
FORM sel_records .
SELECT vbeln
erdat
vkorg
spart
INTO TABLE it_vbak
FROM vbak
WHERE vbeln IN ss_vbeln.
IF sy-subrc <> 0.
MESSAGE e000.
ENDIF.
SELECT vbeln
posnr
matnr
netpr
netwr
INTO TABLE it_vbap
FROM vbap
FOR ALL ENTRIES IN it_vbak
WHERE vbeln = it_vbak-vbeln.
IF sy-subrc <> 0.
MESSAGE e000.
ENDIF.
ENDFORM. " sel_records
*& Form join_tables
* text
* --> p1 text
* <-- p2 text
FORM join_tables .
SORT it_vbak BY vbeln.
SORT it_vbap BY vbeln posnr.
LOOP AT it_vbap INTO wa_vbap.
READ TABLE it_vbak INTO wa_vbak WITH KEY vbeln = wa_vbap-vbeln
BINARY SEARCH.
wa_final-vbeln = wa_vbak-vbeln.
wa_final-erdat = wa_vbak-erdat.
wa_final-vkorg = wa_vbak-vkorg.
wa_final-spart = wa_vbak-spart.
wa_final-posnr = wa_vbap-posnr.
wa_final-matnr = wa_vbap-matnr.
wa_final-netpr = wa_vbap-netpr.
wa_final-netwr = wa_vbap-netwr.
APPEND wa_final TO it_final.
CLEAR wa_final.
ENDLOOP.
ENDFORM. " join_tables
*& Form alv_output
* text
* --> p1 text
* <-- p2 text
FORM alv_output .
CALL SCREEN 2008.
ENDFORM. " alv_output
*& Form alv_layout
* text
* --> p1 text
* <-- p2 text
FORM alv_layout .
wa_layout-grid_title = 'SALES ORDER'.
wa_layout-zebra = 'X'.
ENDFORM. " alv_layout
*& Form fieldcatalog_display
* text
* --> p1 text
* <-- p2 text
FORM fieldcatalog_display .
* IT_FINAL-VBELN. SALES ORDER NUMBER
CLEAR wa_fcat.
wa_fcat-col_pos ='2'.
wa_fcat-fieldname ='VBELN'.
wa_fcat-tabname ='IT_FINAL'.
wa_fcat-key = 'X'.
wa_fcat-just = 'L'.
wa_fcat-hotspot = ' '.
wa_fcat-lzero ='X'.
wa_fcat-seltext ='SALES ORDER NO.'.
wa_fcat-outputlen = 15.
wa_fcat-ref_table ='VBAK'.
APPEND wa_fcat TO it_fcat.
* IT_FINAL-POSNR. SALES ITEM NUMBER
CLEAR wa_fcat.
wa_fcat-col_pos ='3'.
wa_fcat-fieldname ='POSNR'.
wa_fcat-tabname ='IT_FINAL'.
wa_fcat-key = 'X'.
wa_fcat-just = 'L'.
wa_fcat-hotspot = ' '.
wa_fcat-lzero ='X'.
wa_fcat-seltext ='SALES ITEM NO'.
wa_fcat-outputlen = 15.
wa_fcat-ref_table ='VBAP'.
APPEND wa_fcat TO it_fcat.
* IT_FINAL-ERDAT. DATE ON WHICH DOCUMENT WAS CREATED
CLEAR wa_fcat.
wa_fcat-col_pos ='4'.
wa_fcat-fieldname ='ERDAT'.
wa_fcat-tabname ='IT_FINAL'.
wa_fcat-key = ' '.
wa_fcat-just = 'L'.
wa_fcat-hotspot = ' '.
wa_fcat-lzero ='X'.
wa_fcat-seltext ='DATE OF CREATION'.
wa_fcat-outputlen = 10.
wa_fcat-ref_table ='VBAK'.
APPEND wa_fcat TO it_fcat.
* IT_FINAL-VKORG. SALES ORGANIZATION
CLEAR wa_fcat.
wa_fcat-col_pos ='5'.
wa_fcat-fieldname ='VKORG'.
wa_fcat-tabname ='IT_FINAL'.
wa_fcat-key = ' '.
wa_fcat-just = 'L'.
wa_fcat-hotspot = ' '.
wa_fcat-lzero ='X'.
wa_fcat-seltext ='SALES ORG'.
wa_fcat-outputlen = 10.
wa_fcat-ref_table ='VBAK'.
APPEND wa_fcat TO it_fcat.
* IT_FINAL-SPART. DIVISION
CLEAR wa_fcat.
wa_fcat-col_pos ='6'.
wa_fcat-fieldname ='SPART'.
wa_fcat-tabname ='IT_FINAL'.
wa_fcat-key = ' '.
wa_fcat-just = 'L'.
wa_fcat-hotspot = ' '.
wa_fcat-lzero ='X'.
wa_fcat-seltext ='DIVISION'.
wa_fcat-outputlen = 10.
wa_fcat-ref_table ='VBAK'.
APPEND wa_fcat TO it_fcat.
* IT_FINAL-MATNR. MATERIAL NUMBER
CLEAR wa_fcat.
wa_fcat-col_pos ='7'.
wa_fcat-fieldname ='MATNR'.
wa_fcat-tabname ='IT_FINAL'.
wa_fcat-key = ' '.
wa_fcat-just = 'L'.
wa_fcat-hotspot = ' '.
wa_fcat-lzero ='X'.
wa_fcat-seltext ='MATERIAL NUMBER'.
wa_fcat-outputlen = 20.
wa_fcat-ref_table ='VBAP'.
APPEND wa_fcat TO it_fcat.
* IT_FINAL-NETPR. NET PRICE
CLEAR wa_fcat.
wa_fcat-col_pos ='8'.
wa_fcat-fieldname ='NETPR'.
wa_fcat-tabname ='IT_FINAL'.
wa_fcat-key = ' '.
wa_fcat-just = 'L'.
wa_fcat-hotspot = ' '.
wa_fcat-lzero ='X'.
wa_fcat-seltext ='NET PRICE'.
wa_fcat-outputlen = 15.
wa_fcat-ref_table ='VBAP'.
APPEND wa_fcat TO it_fcat.
* IT_FINAL-NETWR. NAET VALUE
CLEAR wa_fcat.
wa_fcat-col_pos ='9'.
wa_fcat-fieldname ='NETWR'.
wa_fcat-tabname ='IT_FINAL'.
wa_fcat-key = ' '.
wa_fcat-just = 'L'.
wa_fcat-hotspot = ' '.
wa_fcat-lzero ='X'.
wa_fcat-seltext ='NET VALUE'.
wa_fcat-outputlen = 15.
wa_fcat-ref_table ='VBAP'.
APPEND wa_fcat TO it_fcat.
ENDFORM. " fieldcatalog_display
Regards,
Darpana.
Edited by: Darpana Ahire on Dec 3, 2008 7:10 AM
Edited by: Matt on Dec 4, 2008 12:04 PM - added tagsim99_chs wrote:
I have created a package with some functions in it.Keep in mind that these functions requires PL/SQL code to be executed. Thus it needs a context switch from the SQL engine (executing your view code) to the PL/SQL engine (to do the function call).
This may work fine for smaller data sets. But it does not scale well as context switches are expensive operations with inherent latency. The more switches there are, the bigger the execution time chunk required for context switching.
The ideal is to rather use SQL to perform the work of the function. SQL code can implement if-then-else logic via the DECODE() SQL function and SQL CASE command. Analytical functions can be used for complex aggregation and calculation.
If a user define (PL/SQL) function is needed, then ensure that the function is as fast as possible (minimal moving parts), and consider defining it as a deterministic function if the same input always produces the same output. -
Using User Defined Function is SQL
Hi
I did the following test to see how expensive it is to use user defined functions in SQL queries, and found that it is really expensive.
Calling SQRT in SQL costs less than calling a dummy function that just returns
the parameter value; this has to do with context switchings, but how can we have
a decent performance compared to Oracle provided functions?
Any comments are welcome, specially regarding the performance of UDF in sql
and for solutions.
create or replace function f(i in number) return number is
begin
return i;
end;
declare
l_start number;
l_elapsed number;
n number;
begin
select to_char(sysdate, 'sssssss')
into l_start
from dual;
for i in 1 .. 20 loop
select max(rownum)
into n
from t_tdz12_a0090;
end loop;
select to_char(sysdate, 'sssssss') - l_start
into l_elapsed
from dual;
dbms_output.put_line('first: '||l_elapsed);
select to_char(sysdate, 'sssssss')
into l_start
from dual;
for i in 1 .. 20 loop
select max(sqrt(rownum))
into n
from t_tdz12_a0090;
end loop;
select to_char(sysdate, 'sssssss') - l_start
into l_elapsed
from dual;
dbms_output.put_line('second: '||l_elapsed);
select to_char(sysdate, 'sssssss')
into l_start
from dual;
for i in 1 .. 20 loop
select max(f(rownum))
into n
from t_tdz12_a0090;
end loop;
select to_char(sysdate, 'sssssss') - l_start
into l_elapsed
from dual;
dbms_output.put_line('third: '||l_elapsed);
end;
Results:
first: 303
second: 1051
third: 1515
Kind regards
TaoufikI find that inline SQL is bad for performance but
good to simplify SQL. I keep thinking that it should
be possible somehow to use a function to improve
performance but have never seen that happen.inline SQL is only bad for performance if the database design (table structure, indexes etc.) is poor or the way the SQL is written is poor.
Context switching between SQL and PL/SQL for a User defined function is definitely a way to slow down performance.
Obviously built-in Oracle functions are going to be quicker than User-defined functions because they are written into the SQL and PL/SQL engines and are optimized for the internals of those engines.
There are a few things you can do to improve function
performance, shaving microseconds off execution time.
Consider using the NOCOPY hints for your parameters
to use pointers instead of copying values. NOCOPY
is a hint rather than a directive so it may or may
not work. Optimize any SQL in the called function.
Don't do anything in loops that does not have to be
done inside a loop.Well, yes, but it's even better to keep all processing in SQL where possible and only resort to PL/SQL when absolutely necessary.
The on-line documentation has suggested that using a
DETERMINISTIC function can improve performance but I
have not been able to demonstrate this and there are
notes in Metalink suggesting that this does not
happen. My experience is that DETERMINISTIC
functions always get executed. There's supposed to
be a feature in 11g that acually caches function
return values.Deterministic functions will work well if used in conjunction with a function based index. That can improve access times when querying data on the function results.
You can use DBMS_PROFILER to get run-time statistics
for each line of your function as it is executed to
help tune it.Or code it as SQL. ;) -
Hi friends ,
I have a requirement where in i need to decode values from my source table while inserting them into my target table. I usually do my task by making functions (don't use case and decode) . My first question is
1) Is using function to accomplish such tasks is good.I have numerous of such conversion requirement .
2)Clubbing subprograms togther into packages is a good habit .But what should be the number of such sub programs .Can i club togther 100 of such functions togther (an average function is of 50 lines) ? If not what should be the segregation thoughts?
3)Are the inbuilt oracle functions like sqrt,length etc deterministic ?
This code represents a typical requirement of mine where in I map my source country name into target's
country id while migrating my data from the source to the target .
create table source
emp_id number,
empname varchar2(100),
sal number,
country varchar2(100)
insert into source values (1,'ALEX',1000,'US');
Insert into source values (2,'RAHUL',2000,'IND');
Insert into source values (3,'KARTIK',3000,'IND');
Insert into source values (4,'SHADOW',5000,'US');
insert into source values(5,'LOUI',1500,'JAP');
Create table source_country_code
country varchar2(100),
abbrv varchar2(100),
area number,
climate varchar2(100)
insert into source_country_code values ('UNITED STATES','US',10000,'COLD');
insert into source_country_code values ('INDIA','IND',100000,'HOT');
insert into source_country_code values ('JAPAN','JAP',1000000,'MODERATE');
Create table target_country_code
country_id number,
descr varchar2(100),
density number,
weather varchar2(100)
insert into target_country_code values (101,'this is descrition txt 1',1001,'COLD');
insert into target_country_code values (102,'this is descrition txt 2',1001,'HOT');
insert into target_country_code values (103,'this is descrition txt 3',1001,'MODERATE');
create table target
emp_id number,
empname varchar2(100),
sal number,
country_id number
);i am typically making functions for such kind of mappings .I have numerous of such requirements as stated above and the
cardinality of the data is high .
create or replace function transform (in_src_country varchar2) return number deterministic
as
l_country_id number;
l_climate varchar2(1000);
begin
select climate into l_climate from source_country_code
where upper(abbrv)=upper(in_src_country);
select country_id into l_country_id
from target_country_code
where upper(weather)=upper(l_climate);
return(l_country_id);
exception
when no_data_found then
return null;
end;final step ,
so ,what i usually do is
insert into target
select emp_id,empname,sal,transform(country) from source;
Thanks as always,
Rahul
Edited by: Rahul K on Jun 5, 2013 10:51 AMRahul K wrote:
Hi friends ,
I have a requirement where in i need to decode values from my source table while inserting them into my target table. I usually do my task by making functions (don't use case and decode) . My first question is
1) Is using function to accomplish such tasks is good.I have numerous of such conversion requirement .Not really. If the functions are sufficiently complex then sometimes there's no way around it. However you're going to pay the price if you try to add this to a SQL query (your query won't scale in the least).
Rahul K wrote:
2)Clubbing subprograms togther into packages is a good habit .But what should be the number of such sub programs .Can i club togther 100 of such functions togther (an average function is of 50 lines) ? If not what should be the segregation thoughts?Yeah, put as many as makes sense. Generally you would want to separate them in some logical fashion, by business function, or some other convention.
Rahul K wrote:
3)Are the inbuilt oracle functions like sqrt,length etc deterministic ? http://docs.oracle.com/cd/E11882_01/appdev.112/e25518/adfns_packages.htm#ADFNS386
A deterministic function depends solely on the values passed into it as arguments and does not reference or modify the contents of package variables or the database or have other side-effects. Such a function produces the same result value for any combination of argument values passed into it.
So yes. They are.
Rahul K wrote:
This code represents a typical requirement of mine where in I map my source country name into target's
country id while migrating my data from the source to the target .
create table source
emp_id number,
empname varchar2(100),
sal number,
country varchar2(100)
insert into source values (1,'ALEX',1000,'US');
Insert into source values (2,'RAHUL',2000,'IND');
Insert into source values (3,'KARTIK',3000,'IND');
Insert into source values (4,'SHADOW',5000,'US');
insert into source values(5,'LOUI',1500,'JAP');
Create table source_country_code
country varchar2(100),
abbrv varchar2(100),
area number,
climate varchar2(100)
insert into source_country_code values ('UNITED STATES','US',10000,'COLD');
insert into source_country_code values ('INDIA','IND',100000,'HOT');
insert into source_country_code values ('JAPAN','JAP',1000000,'MODERATE');
Create table target_country_code
country_id number,
descr varchar2(100),
density number,
weather varchar2(100)
insert into target_country_code values (101,'this is descrition txt 1',1001,'COLD');
insert into target_country_code values (102,'this is descrition txt 2',1001,'HOT');
insert into target_country_code values (103,'this is descrition txt 3',1001,'MODERATE');
create table target
emp_id number,
empname varchar2(100),
sal number,
country_id number
);i am typically making functions for such kind of mappings .I have numerous of such requirements as stated above and the
cardinality of the data is high .
create or replace function transform (in_src_country varchar2) return number deterministic
as
l_country_id number;
l_climate varchar2(1000);
begin
select climate into l_climate from source_country_code
where upper(abbrv)=upper(in_src_country);
select country_id into l_country_id
from target_country_code
where upper(weather)=upper(l_climate);
return(l_country_id);
exception
when no_data_found then
return null;
end;final step ,
so ,what i usually do is
insert into target
select emp_id,empname,sal,transform(country) from source;
Thanks as always,
Rahul
Edited by: Rahul K on Jun 5, 2013 10:51 AMYou would be much better (leaps and bounds better) off incorporating that logic directly into your SQL statement.
Cheers, -
Scaleability with Functions in SQL queries
Hi,
In one of our applications we have many views that use a packaged function in the where clause to filter data. This function uses a SYS_CONTEXT() to set and get values. There are couple of issues while using this approach:
1/ The deterministic function doesn't allow any scability with PQ-server.
2/ Another issue with this function and also the SYS_CONTEXT-function, they manuipulate the estimated CBO-statistics.
CREATE TABLE TAB_I
COLUMN1 NUMBER(16, 0) NOT NULL
, COLUMN2 VARCHAR2(20)
, CONSTRAINT TAB_I_PK PRIMARY KEY
COLUMN1
ENABLE
CREATE TABLE TAB_V
I_COL1 NUMBER(16,0) NOT NULL ENABLE,
VERSION_ID NUMBER(16,0) NOT NULL ENABLE,
CRE_DATIM TIMESTAMP (6) NOT NULL ENABLE,
TERM_DATIM TIMESTAMP (6) NOT NULL ENABLE,
VERSION_VALID_FROM DATE NOT NULL ENABLE,
VERSION_VALID_TILL DATE NOT NULL ENABLE,
CONSTRAINT TAB_V_PK PRIMARY KEY (I_COL1, VERSION_ID) USING INDEX NOCOMPRESS LOGGING ENABLE,
CONSTRAINT COL1_FK FOREIGN KEY (I_COL1) REFERENCES TAB_I (COLUMN1) ENABLE
CREATE OR REPLACE
PACKAGE app_bitemporal_rules IS
FUNCTION f_knowledge_time RETURN TIMESTAMP DETERMINISTIC;
END app_bitemporal_rules;
create or replace
PACKAGE BODY app_bitemporal_rules IS
FUNCTION f_knowledge_time RETURN TIMESTAMP DETERMINISTIC IS
BEGIN
RETURN TO_TIMESTAMP(SYS_CONTEXT ('APP_USR_CTX', 'KNOWLEDGE_TIME'),'DD.MM.YYYY HH24.MI.SSXFF');
END f_knowledge_time;
END app_bitemporal_rules;
explain plan for select *
FROM tab_i
JOIN tab_v
ON tab_i.column1 = tab_v.i_col1
AND app_bitemporal_rules.f_knowledge_time BETWEEN tab_v.CRE_DATIM AND tab_v.TERM_DATIM
where tab_i.column1 = 11111;
select * from table(dbms_xplan.display);
Plan hash value: 621902595
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 95 | 5 (0)| 00:00:06 |
| 1 | NESTED LOOPS | | 1 | 95 | 5 (0)| 00:00:06 |
| 2 | TABLE ACCESS BY INDEX ROWID| TAB_I | 1 | 25 | 1 (0)| 00:00:02 |
|* 3 | INDEX UNIQUE SCAN | TAB_I_PK | 1 | | 1 (0)| 00:00:02 |
|* 4 | TABLE ACCESS FULL | TAB_V | 1 | 70 | 4 (0)| 00:00:05 |
Predicate Information (identified by operation id):
3 - access("TAB_I"."COLUMN1"=11111)
4 - filter("TAB_V"."I_COL1"=11111 AND
"TAB_V"."CRE_DATIM"<="APP_BITEMPORAL_RULES"."F_KNOWLEDGE_TIME"() AND
"TAB_V"."TERM_DATIM">="APP_BITEMPORAL_RULES"."F_KNOWLEDGE_TIME"())
Note
- 'PLAN_TABLE' is old version
- dynamic sampling used for this statement (level=2)
explain plan for select *
FROM tab_i
JOIN tab_v
ON tab_i.column1 = tab_v.i_col1
AND '10-OCT-2011' BETWEEN tab_v.CRE_DATIM AND tab_v.TERM_DATIM
where tab_i.column1 = 11111;
select * from table(dbms_xplan.display);
Plan hash value: 621902595
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 256 | 24320 | 5 (0)| 00:00:06 |
| 1 | NESTED LOOPS | | 256 | 24320 | 5 (0)| 00:00:06 |
| 2 | TABLE ACCESS BY INDEX ROWID| TAB_I | 1 | 25 | 1 (0)| 00:00:02 |
|* 3 | INDEX UNIQUE SCAN | TAB_I_PK | 1 | | 1 (0)| 00:00:02 |
|* 4 | TABLE ACCESS FULL | TAB_V | 256 | 17920 | 4 (0)| 00:00:05 |
Predicate Information (identified by operation id):
3 - access("TAB_I"."COLUMN1"=11111)
4 - filter("TAB_V"."I_COL1"=11111 AND "TAB_V"."CRE_DATIM"<=TIMESTAMP'
2011-10-10 00:00:00.000000000' AND "TAB_V"."TERM_DATIM">=TIMESTAMP' 2011-10-10
00:00:00.000000000')
Note
- 'PLAN_TABLE' is old version
- dynamic sampling used for this statement (level=2) As can be seen in the second plan the cardinality has been guessed correctly, but not in the first case.
I have also tried with:
ASSOCIATE STATISTICS WITH packages app_bitemporal_rules DEFAULT COST (1000000/*246919*/,1000,0) DEFAULT SELECTIVITY 50;
But, this just leads to a increased cost, but no change in cardinality.
The (1) problem gets solved if I directly use "TO_TIMESTAMP(SYS_CONTEXT ('APP_USR_CTX', 'KNOWLEDGE_TIME'),'DD.MM.YYYY HH24.MI.SSXFF')" in the where clause. But am not able to find a solution for the (2) issue.
Can you please help.
Regards,
Vikram RHi Vikram,
On the subject of using [url http://download.oracle.com/docs/cd/E11882_01/server.112/e26088/statements_4006.htm#i2115932]ASSOCIATE STATISTICS, having done a little investigation on 11.2.0.2, I'm having trouble adjusting selectivity via "associate statististics ... default selectivity" but no problems with adjusting default cost.
I've also tried to do the same using an interface type and am running into other issues.
It's not functionality that I'm overly familiar with as I try to avoid/eliminate using functions in predicates.
Further analysis/investigation required.
Including test case of what I've done so far in case anyone else wants to chip in.
SQL> select * from v$version;
BANNER
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE 11.2.0.2.0 Production
TNS for Linux: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production
SQL> drop table t1;
Table dropped.
SQL>
SQL> create table t1
2 as
3 select rownum col1
4 from dual
5 connect by rownum <= 100000;
Table created.
SQL>
SQL> exec dbms_stats.gather_table_stats(USER,'T1');
PL/SQL procedure successfully completed.
SQL>
SQL> create or replace function f1
2 return number
3 as
4 begin
5 return 1;
6 end;
7 /
Function created.
SQL>
SQL> create or replace function f2 (
2 i_col1 in number
3 )
4 return number
5 as
6 begin
7 return 1;
8 end;
9 /
Function created.
SQL> Created one table with 100000 rows.
Two functions - one without arguments, one with (for later).
With no associations:
SQL> select * from user_associations;
no rows selected
SQL> Run a statement that uses the function:
SQL> select count(*) from t1 where col1 >= f1;
COUNT(*)
100000
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
SQL_ID gm7ppkbzut114, child number 0
select count(*) from t1 where col1 >= f1
Plan hash value: 3724264953
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | | | 139 (100)| |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | TABLE ACCESS FULL| T1 | 5000 | 25000 | 139 (62)| 00:00:01 |
Predicate Information (identified by operation id):
2 - filter("COL1">="F1"())
19 rows selected.
SQL> Shows that default selectivity of 5% for an equality predicate against function.
Let's try to adjust the selectivity using associate statistics - the argument for selectivity should be a percentage between 0 and 100:
(turning off cardinality feedback for clarity/simplicity)
SQL> alter session set "_optimizer_use_feedback" = false;
Session altered.
SQL>
SQL> ASSOCIATE STATISTICS WITH FUNCTIONS f1 default selectivity 100;
Statistics associated.
SQL> select count(*) from t1 where col1 >= f1;
COUNT(*)
100000
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
SQL_ID gm7ppkbzut114, child number 1
select count(*) from t1 where col1 >= f1
Plan hash value: 3724264953
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | | | 139 (100)| |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | TABLE ACCESS FULL| T1 | 5000 | 25000 | 139 (62)| 00:00:01 |
Predicate Information (identified by operation id):
2 - filter("COL1">="F1"())
19 rows selected.
SQL> Didn't make any difference to selectivity.
An excerpt from a 10053 trace file had the following:
** Performing dynamic sampling initial checks. **
** Dynamic sampling initial checks returning FALSE.
No statistics type defined for function F1
No default cost defined for function F1So, crucially what's missing here is a clause saying:
No default selectivity defined for function F1But there's no other information that I could see to indicate why it should be discarded.
Moving on, adjusting the cost does happen:
SQL>exec spflush;
PL/SQL procedure successfully completed.
SQL> disassociate statistics from functions f1;
Statistics disassociated.
SQL>
SQL> ASSOCIATE STATISTICS WITH FUNCTIONS f1 default selectivity 100 default cost (100,5,0);
Statistics associated.
SQL> select count(*) from t1 where col1 >= f1;
COUNT(*)
100000
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
SQL_ID gm7ppkbzut114, child number 0
select count(*) from t1 where col1 >= f1
Plan hash value: 3724264953
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | | | 500K(100)| |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | TABLE ACCESS FULL| T1 | 5000 | 25000 | 500K (1)| 00:41:41 |
Predicate Information (identified by operation id):
2 - filter("COL1">="F1"())
19 rows selected.
SQL> And we see the following in a 10053:
No statistics type defined for function F1
Default costs for function F1 CPU: 100, I/O: 5So, confirmation that default costs for function were found and applied but nothing else about selectivity again.
I wondered whether the lack of arguments for function F1 made any difference, hence function F2.
Didn't seem to:
Vanilla:
SQL> select count(*) from t1 where col1 >= f2(col1);
COUNT(*)
100000
SQL>
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
SQL_ID 2wxw32wadgc1v, child number 0
select count(*) from t1 where col1 >= f2(col1)
Plan hash value: 3724264953
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | | | 139 (100)| |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | TABLE ACCESS FULL| T1 | 5000 | 25000 | 139 (62)| 00:00:01 |
Predicate Information (identified by operation id):
2 - filter("COL1">="F2"("COL1"))
19 rows selected.
SQL> Plus association:
SQL>exec spflush;
PL/SQL procedure successfully completed.
SQL>
SQL> associate statistics with functions f2 default selectivity 90 default cost (100,5,0);
Statistics associated.
SQL> select count(*) from t1 where col1 >= f2(col1);
COUNT(*)
100000
SQL>
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
SQL_ID 2wxw32wadgc1v, child number 0
select count(*) from t1 where col1 >= f2(col1)
Plan hash value: 3724264953
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | | | 500K(100)| |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | TABLE ACCESS FULL| T1 | 5000 | 25000 | 500K (1)| 00:41:41 |
Predicate Information (identified by operation id):
2 - filter("COL1">="F2"("COL1"))
19 rows selected.
SQL> Just to confirm associations:
SQL> select * from user_associations;
OBJECT_OWNER OBJECT_NAME COLUMN_NAME OBJECT_TY
STATSTYPE_SCHEMA STATSTYPE_NAME DEF_SELECTIVITY DEF_CPU_COST DEF_IO_COST DEF_NET_COST
INTERFACE_VERSION MAINTENANCE_TY
RIMS F2 FUNCTION
90 100 5
0 USER_MANAGED
RIMS F1 FUNCTION
100 100 5
0 USER_MANAGED
SQL> So.... started thinking about whether using an interface type would help?
SQL> CREATE OR REPLACE TYPE test_stats_ot AS OBJECT
2 (dummy_attribute NUMBER
3 ,STATIC FUNCTION ODCIGetInterfaces (
4 ifclist OUT SYS.ODCIObjectList
5 ) RETURN NUMBER
6 ,STATIC FUNCTION ODCIStatsSelectivity (
7 pred IN SYS.ODCIPredInfo,
8 sel OUT NUMBER,
9 args IN SYS.ODCIArgDescList,
10 strt IN NUMBER,
11 stop IN NUMBER,
12 --i_col1 in NUMBER,
13 env IN SYS.ODCIEnv
14 ) RETURN NUMBER
15 --,STATIC FUNCTION ODCIStatsFunctionCost (
16 -- func IN SYS.ODCIPredInfo,
17 -- cost OUT SYS.ODCICost,
18 -- args IN SYS.ODCIArgDescList,
19 -- i_col1 in NUMBER,
20 -- env IN SYS.ODCIEnv
21 -- ) RETURN NUMBER
22 );
23 /
Type created.
SQL> CREATE OR REPLACE TYPE BODY test_stats_ot
2 AS
3 STATIC FUNCTION ODCIGetInterfaces (
4 ifclist OUT SYS.ODCIObjectList
5 ) RETURN NUMBER
6 IS
7 BEGIN
8 ifclist := sys.odciobjectlist(sys.odciobject('SYS','ODCISTATS2'));
9 RETURN odciconst.success;
10 END;
11 STATIC FUNCTION ODCIStatsSelectivity
12 (pred IN SYS.ODCIPredInfo,
13 sel OUT NUMBER,
14 args IN SYS.ODCIArgDescList,
15 strt IN NUMBER,
16 stop IN NUMBER,
17 --i_col1 in NUMBER,
18 env IN SYS.ODCIEnv)
19 RETURN NUMBER
20 IS
21 BEGIN
22 sel := 90;
23 RETURN odciconst.success;
24 END;
25 -- STATIC FUNCTION ODCIStatsFunctionCost (
26 -- func IN SYS.ODCIPredInfo,
27 -- cost OUT SYS.ODCICost,
28 -- args IN SYS.ODCIArgDescList,
29 -- i_col1 in NUMBER,
30 -- env IN SYS.ODCIEnv
31 -- ) RETURN NUMBER
32 -- IS
33 -- BEGIN
34 -- cost := sys.ODCICost(10000,5,0,0);
35 -- RETURN odciconst.success;
36 -- END;
37 END;
38 /
Type body created.
SQL> But this approach is not happy - perhaps not liking the function with no arguments?
SQL> disassociate statistics from functions f1;
Statistics disassociated.
SQL> ASSOCIATE STATISTICS WITH FUNCTIONS f1 USING test_stats_ot;
Statistics associated.
SQL> select count(*) from t1 where col1 >= f1;
select count(*) from t1 where col1 >= f1
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-06550: line 12, column 22:
PLS-00103: Encountered the symbol "ÀÄ" when expecting one of the following:
) , * & = - + < / > at in is mod remainder not rem =>
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || multiset member submultiset
SQL> So, back to F2 again (uncommenting argument i_col1 in ODCIStatsSelectivity):
SQL> disassociate statistics from functions f1;
Statistics disassociated.
SQL> disassociate statistics from functions f2;
Statistics disassociated.
SQL> ASSOCIATE STATISTICS WITH FUNCTIONS f2 USING test_stats_ot;
Statistics associated.
SQL> select count(*) from t1 where col1 >= f2(col1);
COUNT(*)
100000
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
SQL_ID 2wxw32wadgc1v, child number 0
select count(*) from t1 where col1 >= f2(col1)
Plan hash value: 3724264953
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | | | 139 (100)| |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | TABLE ACCESS FULL| T1 | 5000 | 25000 | 139 (62)| 00:00:01 |
Predicate Information (identified by operation id):
2 - filter("COL1">="F2"("COL1"))
19 rows selected.
SQL> Nothing obviously happening.
You'll note also in my interface type implementation that I commented out a declaration of ODCIStatsFunctionCost.
This post is probably already too long already so I've skipped some of the detail.
But when ODCIStatsFunctionCost was used with function F2, I presume I've made a mistake in the implementation because I had an error in the 10053 trace as follows:
Calling user-defined function cost function...
predicate: "RIMS"."F2"("T1"."COL1")
declare
cost sys.ODCICost := sys.ODCICost(NULL, NULL, NULL, NULL);
arg0 NUMBER := null;
begin
:1 := "RIMS"."TEST_STATS_OT".ODCIStatsFunctionCost(
sys.ODCIFuncInfo('RIMS',
'F2',
NULL,
1),
cost,
sys.ODCIARGDESCLIST(sys.ODCIARGDESC(2, 'T1', 'RIMS', '"COL1"', NULL, NULL, NULL))
, arg0,
sys.ODCIENV(:5,:6,:7,:8));
if cost.CPUCost IS NULL then
:2 := -1.0;
else
:2 := cost.CPUCost;
end if;
if cost.IOCost IS NULL then
:3 := -1.0;
else
:3 := cost.IOCost;
end if;
if cost.NetworkCost IS NULL then
:4 := -1.0;
else
:4 := cost.NetworkCost;
end if;
exception
when others then
raise;
end;
ODCIEnv Bind :5 Value 0
ODCIEnv Bind :6 Value 0
ODCIEnv Bind :7 Value 0
ODCIEnv Bind :8 Value 4
ORA-6550 received when calling RIMS.TEST_STATS_OT.ODCIStatsFunctionCost -- method ignoredThere was never any such feedback about ODCIStatsSelectivity.
So, in summary, more questions than answers.
I'll try to have another look later. -
Oracle result cache and functions
Hi All,
I am on 11.2 in Linux.
I want to use Oracle's result cache to cache results of (user defined) functions, which we use in SELECT commands.
My question is, does result caching work for deterministic and non-deterministic functions ?
Just curious, how Oracle keeps track of changes being made which affect a function's return value?
Thoughts please.
Thanks in advanceI want to ... cache results of (user defined) functions, which we use in SELECT commands.You have four choices:
1. Subquery caching - (wrap function call in SELECT) useful for repeated function calls in a single SELECT
2. Marking function as DETERMINISTIC - inconsistent results across versions, deterministic best reserved for function-based indexes only
3. Result Cache
4. Move function logic out of function and inline to the main SQL statement.
The biggest downside of any function call that is inline to SQL is that it bypasses the read consistency mechanism, actually that's probably the second biggest downside. The biggest downside is normally that their misuse kills performance.
If your function itself contains SQL then you should seriously reconsider whether you should be using a function.
does result caching work for deterministic and non-deterministic functions ?Result cache knows nothing about determinism so yes it should be applied regardless.
Oracle keeps track of changes being made which affect a function's return value?See v$result_cache_dependency.
The mechanism is very blunt, there is no fine-grained tracking of data changes that may affect your result.
It's as simple as function F1 relies on table T1. If the data in table T1 changes, invalidate the results in the result cache for F1. -
Creating function-based indexes
I'm trying to create a function-based index in one of the user's schemas and am getting an insufficient privilege error. Below are the examples:
connect scott/tiger ;
CREATE INDEX emp_ename_idx ON ename( emp ) ;
Index created.
CREATE INDEX upper_ename_idx ON ename( upper(ename)) ;
ERROR at line1:
ORA-01031: insufficient privileges
The DBA granted the CREATE ANY INDEX privilege to user scott already. Any ideas???
Thanks,
SYHi, all.
I didn't hear about function-based index before, so I did some testing. Instead of using Oracle predefined functions (upper, lower, substr etc.), I created my own function and tried to create an index on it. I received an error that function is not deterministic. The definition of deterministic from Oracle docs:
DETERMINISTIC
This hint helps the optimizer avoid redundant function calls. If a stored function was called previously with the same arguments, the optimizer can elect to use the previous result. The function result should not depend on the state of session variables or schema objects. Otherwise, results might vary across calls. Only DETERMINISTIC functions can be called from a function-based index or a materialized view that has query-rewrite enabled.
So, I put word deterministic in function declaration and everything works OK. Then I modified function to use some of the tables (I used tables across different schemas), recreated the index and it also worked fine.
Question - is this statement correct: You can use schema objects in function which is in turn used for indexes as long as you put word deterministic in function declaration and all objects (function, index) will be valid, but ORACLE doesn't guarantee that result produced using that index will be correct?
Thank you. -
ORA-04091 (table string.string is mutating) and Function-Based Index
I've encountered a problem with DELETEing from a table when that table has a function-based index on it. The following demonstrates this:
SQL> CREATE OR REPLACE FUNCTION get_employee_location(p_empno IN number)
2 RETURN varchar2
3 DETERMINISTIC
4 IS
5 l_return_value varchar2(20);
6 BEGIN
7 SELECT loc
8 INTO l_return_value
9 FROM dept
10 WHERE deptno = (SELECT
11 e.deptno
12 FROM emp e
13 WHERE empno = p_empno);
14 return l_return_value;
15 end;
16 /
Function created.
SQL> create index location_idx on emp (get_employee_location(empno));
Index created.
SQL> delete from emp;
delete from emp
ERROR at line 1:
ORA-04091: table SCOTT.EMP is mutating, trigger/function may not see it
ORA-06512: at "SCOTT.GET_EMPLOYEE_LOCATION", line 7------------------------------------------------
The question is: How can I successfully DELETE FROM emp but keep my function-based index in place?
Thanks
Andy'Being able to' is 'being able to', but
it is dangerous to declare "DETERMINISTIC" for non-deterministic function.
The following problem happens on non-deterministic function index.
SQL> update dept set loc = 'NEWYORK' where deptno=10;
1 row updated.
SQL> commit;
Commit complete.
SQL> select * from emp where get_employee_location(deptno)='NEWYORK';
no rows selected
SQL> select * from dept;
DEPTNO DNAME LOC
10 ACCOUNTING NEWYORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL> select empno,ename from emp where get_employee_location(deptno)='NEW YORK';
EMPNO ENAME
7782 CLARK
7839 KING
7934 MILLER
SQL> select empno,ename,get_employee_location(deptno) from emp where deptno=10;
EMPNO ENAME GET_EMPLOYEE_LOCATION(DEPTNO)
7782 CLARK
7839 KING
7934 MILLER
SQL> select empno,ename,get_employee_location(deptno) from emp where get_employee_location(deptno)='NEW YORK';
EMPNO ENAME GET_EMPLOYEE_LOCATION(DEPTNO)
7782 CLARK NEW YORK
7839 KING NEW YORK
7934 MILLER NEW YORK
SQL> drop index location_idx ;
Index dropped.
SQL> select empno,ename from emp where get_employee_location(deptno)='NEW YORK';
no rows selected -
Query result cache with functions
Hi all,
one of my colleagues has found a little bit weird behavior of a query result cache. He has set result_cache_mode = 'FORCE' (but it can be reproduced with a result_cache hint too) and suddenly functions called from the query get executed twice (for the first time) .
An easy example:
alter session set result_cache_mode = 'FORCE';
create sequence test_seq;
create or replace function test_f(i number)
return number
is
begin
dbms_output.put_line('TEST_F executed');
--autonomous transaction or package variable can be used too
return test_seq.nextval;
end;
prompt First call
select test_f(1) from dual;
prompt Second call
select test_f(1) from dual;
drop sequence test_seq;
drop function test_f;
First call
TEST_F(1)
2
TEST_F executed
TEST_F executed
Second call
TEST_F(1)
1
As you can see - for the first time the function is executed twice and return the value from the second execution. When I execute the query again it returns the value from the first execution... but it doesn't matter, problem is in the double execution. Our developers used to send emails via select (it's easier for them):
select send_mail(...) from dual;
... and now the customers complains that they get emails twice
And now the question - is there any way, hot to get rid of this behavior (without changing the parameter back or rewriting code)? I thought that the result cache is automatically disabled for non-deterministic functions...or is this an expected behavior?
Thanks,
IvanInteresting.. you are right:
SELECT /*+ RESULT_CACHE */ 'dog' FROM DUAL;
And at the second execution:
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | RESULT CACHE | cc5k01xyqz3ypf9t0j28r5gtd1 | | | |
| 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
Hmmm..
Maybe you are looking for
-
I downloaded Firefox to my PC and olny get a blank screen when I click on the Icon, Why?
I only had Internet Explorer on this new( to me) PC and wanted to download FireFox. I downloaded it to my PC and when I click on the Firefox Icon, all I get is a blank screen with a small menu bar at the top left. I DO NOT get the icons that show on
-
Stored Procedures - Executing a query with multiple variables
Hello everyone.. During development I faced the followng problem. When I tried to execute a query in a stored procedure using 2 or more variables an unexplained error came up! The fact is that I use a form that calls this particular stored procedure
-
Exporting from Lightroom to Photoshop.
I have set the necessary preferences so as to export from Lightroom to PS CC. However when i try to export a file then PS CC fails to open. However PSE 11 opens but with no file! Any help would be appreciated. thanks GM
-
I downloaded Adobe CS5.5 Master Suite: Missing Setup File
I don't know what to do. My school issued free issue (legally) of Adobe CS5.5 Master collection. I downloaded the whole thing through my Adobe Downloader, but now it is saying that I am missing the setup file. What can I do?
-
When i close called form. i want to refresh calling form.but how?
i am using call_form ( name_in(':Global.App_Path')|| file_name, hide, Do_replace, no_query_only,pl). when i close called form. i want to refresh calling form. how can i do it.