Skip to Main Content

SQL & PL/SQL

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

Make NEXT_DAY() independent of the invoking session's NLS_DATE_LANGUAGE

mathguyMar 6 2017 — edited Mar 10 2017

The function NEXT_DAY() takes two arguments. The first argument is a date and the second is a string expression, the name of a "day of the week". For example, if the second argument is 'Tuesday', the function will return the earliest date that is a Tuesday and is strictly later than the first argument. The "day of the week" argument must be in the NLS_DATE_LANGUAGE of the session in which the function is invoked. So, for example, if I ALTER SESSION to set the NLS_DATE_LANGUAGE to 'German' or 'French', I will get an error message if I use NEXT_DAY(..., 'Tuesday').

https://docs.oracle.com/database/121/SQLRF/functions118.htm#SQLRF00672

Note (irrelevant for this discussion): only the first three letters in the day name are relevant, the rest is ignored so it can be garbage; I could use 'Tuemathguy' and the function would work OK in English. "Three" letters is for English; whatever the correct number of letters in the abbreviation of day-of-the-week names in the NLS_DATE_LANGUAGE is the relevant number of letters for the NEXT_DAY() function.

Unfortunately, unlike many other functions that have to do with dates, NEXT_DAY() does not take an argument for NLS_DATE_LANGUAGE. So a query that uses NEXT_DAY() will require a hack, if it is meant to be run in different locations and we don't want to ask the invoker to alter their session to set their NLS_DATE_LANGUAGE to a fixed value, such as 'English'.

I can think of two such hacks, but I don't like them. Question: Is there a better way? Of course, it would be best if Oracle would allow a third argument for nlsparam, as they do for other functions...

The hacks are: (1) we can take a known date for the desired day of the week, and use   to_char(that_date, 'Day')    as the second argument to NEXT_DAY();  (2) similarly, instead of using a hard-coded date that is known to be a certain day of the week, we can instead truncate SYSDATE to a Monday, using the 'iw' format model, and then add whatever number we need to get the desired day of the week. Both hacks use the fact that TO_CHAR() returns the name of the day in the NLS_DATE_LANGUAGE of the invoking session. Often we want to override that by specifying NLS_DATE_LANGUAGE explicitly in the function call, but in this case we want just the opposite.

In the illustrations below, I want to find the first Tuesday in August 2017. (Remember, that means I must apply NEXT_DAY() to the date preceding 2017-08-01, because NEXT_DAY() returns a date strictly greater than the first argument. To indicate that very clearly, I will not write 2017-07-31, but I will instead subtract 1 from 2017-08-01.)

SQL> alter session set nls_date_format = 'yyyy-mm-dd';
SQL> alter session set nls_date_language = 'English';

SQL> select next_day(date '2017-08-01' - 1, 'Tuesday') as next_tue from dual;

NEXT_TUE
----------
2017-08-01

OK, so far we know that 2017-08-01 will be a Tuesday. We can and will use this later. (Any other date that is known beforehand to be a Tuesday would work just as well.)

Now let's change the session's date language to German and try to run the same query. It should fail, and it does.

SQL> alter session set nls_date_language = 'German';

SQL> select next_day(date '2017-08-01' - 1, 'Tuesday') as next_tue from dual;
select next_day(date '2017-08-01' - 1, 'Tuesday') as next_tue from dual

                                       *
ERROR at line 1:
ORA-01846: Kein gültiger Wochentag

OK, so let's use the date we know to be a Tuesday, and see what they call it in German. We can use that in our query (but, again, it will be hard-coded, just in a different language - German instead of English).

SQL> select to_char(date '2017-08-01', 'Day') from dual;

TO_CHAR(DA
----------
Dienstag

SQL> select next_day(date '2017-08-01' - 1, 'Dienstag') as next_tue from dual;

NEXT_TUE
----------
2017-08-01

Alright, now let's try the first hack. The query below is independent of the session NLS_DATE_LANGUAGE, but it hard-codes a date known to be a Tuesday. Still not very satisfying.

SQL> select next_day(date '2017-08-01' - 1, to_char(date '2017-08-01', 'Day')) as next_tue from dual;

NEXT_TUE
----------
2017-08-01

Let's test the second hack. First we truncate any date to a Monday, using the 'iw' format model; we add whatever number (1 in this case) to get a Tuesday, and we use TO_CHAR() to get the name of Tuesday in German. Then we pass this value to NEXT_DAY() to make the query independent of NLS_DATE_LANGUAGE. This seems better, as it doesn't require advance knowledge of anything - but it's a lot of work for something that should be much easier. Certainly, if we needed to do this on many rows in a query, we would compute the translation of "Tuesday" in a subquery so we wouldn't have to perform the same computation once for every input row.

SQL> select next_day(date '2017-08-01' - 1, to_char(trunc(sysdate, 'iw') + 1, 'Day')) as next_tue from dual;

NEXT_TUE
----------
2017-08-01

Let's change the NLS_DATE_LANGUAGE to French and test a little more.

SQL> alter session set nls_date_language = 'French';

SQL> select to_char(trunc(sysdate, 'iw') + 1, 'Day') as french_tue from dual;

FRENCH_TUE
----------
Mardi

SQL> select next_day(date '2017-08-01' - 1, to_char(trunc(sysdate, 'iw') + 1, 'Day')) as next_tue from dual;

NEXT_TUE
----------
2017-08-01

Comments

marco
Do you really need UNION ? Maybe UNION ALL is enough? FYI: UNION works as distinct.
Nimish Garg
first point use IN (1,2) in a single query and avoid UNION
second if you want to use UNION, use UNION ALL
santhosh T
Union is to get the distinct records from both the tables and Union all is to get all the records from the both tables, hence the execution plan will be different.
SQL> explain plan for SELECT *
  2    FROM emp
  3  UNION
  4  SELECT *
  5    FROM emp;

Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3774834881

----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |    28 |  1036 |     8  (63)| 00:00:01 |
|   1 |  SORT UNIQUE        |      |    28 |  1036 |     8  (63)| 00:00:01 |
|   2 |   UNION-ALL         |      |       |       |            |          |
|   3 |    TABLE ACCESS FULL| EMP  |    14 |   518 |     3   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL| EMP  |    14 |   518 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------

11 rows selected.

SQL> explain plan for SELECT *
  2    FROM emp
  3  UNION ALL
  4  SELECT *
  5    FROM emp;

Explained.

SQL>  select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1301082189

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    28 |  1036 |     6  (50)| 00:00:01 |
|   1 |  UNION-ALL         |      |       |       |            |          |
|   2 |   TABLE ACCESS FULL| EMP  |    14 |   518 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| EMP  |    14 |   518 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------

10 rows selected.

SQL> select count(*) from (SELECT * FROM emp UNION SELECT * FROM emp);

  COUNT(*)
----------
        14

SQL> SELECT count(*) from ( select * FROM emp UNION ALL SELECT * FROM emp);

  COUNT(*)
----------
        28
Jonathan Lewis
983327 wrote:

when i look at their execution plan seperately, it works fine and no problem but,

when i do this;
select * from emp where emp_no=2
union
select * from emp where emp_no=3;
i see different plan for both.

Is there a way to make use their own plan independently in union statement?
Tell us the version of Oracle, and show us the execution plans first - they we may be able to give you some intelligent advice.

Regards
Jonathan Lewis
User505978 - Oracle
I'm really sorry that i gave little wrong information. My queries are lie the following;

select * from emp where dept_id=10 and emp_id=15

union

select * from emp where dept_id=10 and emp_id=16;


my previous examples were not correct in my first post..

when i look at their plans one by one, i see thet index is used, but when i checked with union, they dont use index.

Off course my real queries are not short like that.
User505978 - Oracle
i tried with union all but it is same, execution plan is changing.
SomeoneElse
What problem are you actually having?
User505978 - Oracle
I'm sending queries and plans. I hope you can und:)it is really long.

Query1

SELECT /*+ use_nl(adres CARD) use_nl(@CUST1 info@CUST1 personal@CUST1) index(@CUST1 personal@CUST1 IX2_MUSTERI_NAME) use_nl(@CUST2 info@CUST2 personal@CUST2) index(@CUST2 personal@CUST2 IX2_CANDIDATE_NAME)*/
'' AS grp_customer_type,
( cst.name || ' ' || cst.midname || ' ' || cst.surname ) as grp_main_customer_info,
card.main_card_no as grp_main_card_info,
card.main_card_no,
card.card_no,
to_char(cst.banking_customer_no),
cst.business_chain_level,
case when cst.business_chain_level in ( 1,2) then 1 else 0 end AS is_dummy_card,
0 AS supp_seq_no,
cst.name,
cst.midname,
cst.surname,
( cst.name || ' ' || cst.midname || ' ' || cst.surname ) as maincardcustomername,
cst.customer_no,
cst.stat_code,
cst.stmt_stat_code,
card.card_level,
card.card_stat_code || '~' || card.card_sub_stat_code cardstatus,
card.emboss_name1,
card.card_type,
card.product_id,
to_char( to_date( case when length( to_char(card.expiry_date) ) < 6 then '190001' else to_char(card.expiry_date) end,'yyyyMM') ,'MM/yyyy') ,
CARD.MAIN_CUSTOMER_NO,
to_char(cst.tc_no),
cst.mother_name,
cst.father_name,
adres.zip_code,
adres.address1,
cst.company_no,
to_char( to_date( to_char(cst.birth_date),'yyyymmdd') ,'dd/MM/yyyy') ,
'' as irtbilgi ,
card.card_branch,
cst.point_collection_type
FROM
OC_CST.CST_CUSTOMER CST,
oc_cst.cst_customer_address_main adres,
OC_CRD.CRD_CARD CARD
WHERE

CARD.CUSTOMER_NO(+) = CST.CUSTOMER_NO
AND CARD.STATUS(+) = 1
AND CST.STATUS(+) = 1
AND cst.banking_customer_no = adres.banking_customer_no(+)
AND cst.post_adress_idx = adres.address_idx(+)
AND CST.MBR_ID = 101
and cst.name like '%ASDF%'


Execution Plan1


SELECT STATEMENT, GOAL = ALL_ROWS 8792467 1305094 464613464
NESTED LOOPS OUTER 8792467 1305094 464613464
NESTED LOOPS OUTER 5219783 892972 238423524
VIEW OC_CST CST_CUSTOMER 3433411 892972 193774924
UNION-ALL
NESTED LOOPS
NESTED LOOPS 3300974 847502 91530216
MAT_VIEW ACCESS BY INDEX ROWID OC_MVT SNAP_UAT_T_MUSTERI 1082860 1083348 56334096
INDEX FULL SCAN OC_SYS IX2_MUSTERI_NAME 57075 1083348
INDEX RANGE SCAN OC_CST IDX_OC_CST_CUSTOMER_NBNKCST_NO 2 2
TABLE ACCESS BY INDEX ROWID OC_CST CST_CUSTOMER_INFO 4 1 56
NESTED LOOPS
NESTED LOOPS 132429 45469 4774245
MAT_VIEW ACCESS BY INDEX ROWID OC_MVT SNAP_UAT_T_CANDIDATE 26817 27326 1338974
INDEX FULL SCAN OC_SYS IX2_CANDIDATE_NAME 1354 27326
INDEX RANGE SCAN OC_CST IDX_OC_CST_CUSTOMER_NBNKCST_NO 2 2
TABLE ACCESS BY INDEX ROWID OC_CST CST_CUSTOMER_INFO 4 2 112
NESTED LOOPS
NESTED LOOPS 7 1 111
TABLE ACCESS STORAGE FULL OC_CST CST_CUSTOMER_TEMP 3 1 55
INDEX RANGE SCAN OC_CST IDX_OC_CST_CUSTOMER_NBNKCST_NO 2 2
TABLE ACCESS BY INDEX ROWID OC_CST CST_CUSTOMER_INFO 4 2 112
MAT_VIEW ACCESS BY INDEX ROWID OC_MVT SNAP_T_ADRES 2 1 50
INDEX UNIQUE SCAN OC_MVT T_ADRES_CLIENT_NO2 1 1
TABLE ACCESS BY INDEX ROWID OC_CRD CRD_CARD 4 1 89
INDEX RANGE SCAN OC_CRD IDX_CRD_CARD_05 2 1






Query2

SELECT /*+ use_nl(adres CARD) use_nl(@CUST1 info@CUST1 personal@CUST1) index(@CUST1 personal@CUST1 IX2_MUSTERI_NAME) use_nl(@CUST2 info@CUST2 personal@CUST2) index(@CUST2 personal@CUST2 IX2_CANDIDATE_NAME)*/
'' AS grp_customer_type,
( cst.name || ' ' || cst.midname || ' ' || cst.surname ) as grp_main_customer_info,
card.main_card_no as grp_main_card_info,
card.main_card_no,
card.card_no,
to_char(cst.banking_customer_no),
cst.business_chain_level,
case when cst.business_chain_level in ( 1,2) then 1 else 0 end AS is_dummy_card,
0 AS supp_seq_no,
cst.name,
cst.midname,
cst.surname,
( cst.name || ' ' || cst.midname || ' ' || cst.surname ) as maincardcustomername,
cst.customer_no,
cst.stat_code,
cst.stmt_stat_code,
card.card_level,
card.card_stat_code || '~' || card.card_sub_stat_code cardstatus,
card.emboss_name1,
card.card_type,
card.product_id,
to_char( to_date( case when length( to_char(card.expiry_date) ) < 6 then '190001' else to_char(card.expiry_date) end,'yyyyMM') ,'MM/yyyy') ,
CARD.MAIN_CUSTOMER_NO,
to_char(cst.tc_no),
cst.mother_name,
cst.father_name,
adres.zip_code,
adres.address1,
cst.company_no,
to_char( to_date( to_char(cst.birth_date),'yyyymmdd') ,'dd/MM/yyyy') ,
'' as irtbilgi ,
card.card_branch,
cst.point_collection_type
FROM
OC_CST.CST_CUSTOMER CST,
oc_cst.cst_customer_address_main adres,
OC_CRD.CRD_CARD CARD
WHERE

CARD.CUSTOMER_NO(+) = CST.CUSTOMER_NO
AND CARD.STATUS(+) = 1
AND CST.STATUS(+) = 1
AND cst.banking_customer_no = adres.banking_customer_no(+)
AND cst.post_adress_idx = adres.address_idx(+)
AND CST.MBR_ID = 101
and cst.name like '%ASDF%'

union

SELECT /*+ use_nl(adres CARD) use_nl(@CUST1 info@CUST1 personal@CUST1) index(@CUST1 personal@CUST1 IX2_MUSTERI_NAME) use_nl(@CUST2 info@CUST2 personal@CUST2) index(@CUST2 personal@CUST2 IX2_CANDIDATE_NAME)*/
'' AS grp_customer_type,
( cst.name || ' ' || cst.midname || ' ' || cst.surname ) as grp_main_customer_info,
card.main_card_no as grp_main_card_info,
card.main_card_no,
card.card_no,
to_char(cst.banking_customer_no),
cst.business_chain_level,
case when cst.business_chain_level in ( 1,2) then 1 else 0 end AS is_dummy_card,
0 AS supp_seq_no,
cst.name,
cst.midname,
cst.surname,
( cst.name || ' ' || cst.midname || ' ' || cst.surname ) as maincardcustomername,
cst.customer_no,
cst.stat_code,
cst.stmt_stat_code,
card.card_level,
card.card_stat_code || '~' || card.card_sub_stat_code cardstatus,
card.emboss_name1,
card.card_type,
card.product_id,
to_char( to_date( case when length( to_char(card.expiry_date) ) < 6 then '190001' else to_char(card.expiry_date) end,'yyyyMM') ,'MM/yyyy') ,
CARD.MAIN_CUSTOMER_NO,
to_char(cst.tc_no),
cst.mother_name,
cst.father_name,
adres.zip_code,
adres.address1,
cst.company_no,
to_char( to_date( to_char(cst.birth_date),'yyyymmdd') ,'dd/MM/yyyy') ,
'' as irtbilgi ,
card.card_branch,
cst.point_collection_type
FROM
OC_CST.CST_CUSTOMER CST,
oc_cst.cst_customer_address_main adres,
OC_CRD.CRD_CARD CARD
WHERE

CARD.CUSTOMER_NO(+) = CST.CUSTOMER_NO
AND CARD.STATUS(+) = 1
AND CST.STATUS(+) = 1
AND cst.banking_customer_no = adres.banking_customer_no(+)
AND cst.post_adress_idx = adres.address_idx(+)
AND CST.MBR_ID = 101
and cst.name2 like '%ASDF%'

Execution Plan2

SELECT STATEMENT, GOAL = ALL_ROWS 16511931 3782374 1380457588
SORT UNIQUE 16511931 3782374 1380457588
UNION-ALL
NESTED LOOPS OUTER 5668526 1305094 498545908
NESTED LOOPS OUTER 2095841 892972 261640796
VIEW OC_CST CST_CUSTOMER 309470 892972 216992196
UNION-ALL
HASH JOIN 286728 847502 91530216
TABLE ACCESS STORAGE FULL OC_CST CST_CUSTOMER_INFO 17674 847502 47460112
MAT_VIEW ACCESS STORAGE FULL OC_MVT SNAP_UAT_T_MUSTERI 263042 1083348 56334096
HASH JOIN 22735 45469 4774245
MAT_VIEW ACCESS STORAGE FULL OC_MVT SNAP_UAT_T_CANDIDATE 5058 27326 1338974
TABLE ACCESS STORAGE FULL OC_CST CST_CUSTOMER_INFO 17674 847502 47460112
NESTED LOOPS
NESTED LOOPS 7 1 111
TABLE ACCESS STORAGE FULL OC_CST CST_CUSTOMER_TEMP 3 1 55
INDEX RANGE SCAN OC_CST IDX_OC_CST_CUSTOMER_NBNKCST_NO 2 2
TABLE ACCESS BY INDEX ROWID OC_CST CST_CUSTOMER_INFO 4 2 112
MAT_VIEW ACCESS BY INDEX ROWID OC_MVT SNAP_T_ADRES 2 1 50
INDEX UNIQUE SCAN OC_MVT T_ADRES_CLIENT_NO2 1 1
TABLE ACCESS BY INDEX ROWID OC_CRD CRD_CARD 4 1 89
INDEX RANGE SCAN OC_CRD IDX_CRD_CARD_05 2 1
FILTER
NESTED LOOPS OUTER 10549034 2477280 881911680
NESTED LOOPS OUTER 3767498 1695006 452566602
VIEW OC_CST CST_CUSTOMER 376674 1695006 367816302
UNION-ALL
HASH JOIN 349626 847502 91530216
TABLE ACCESS STORAGE FULL OC_CST CST_CUSTOMER_INFO 17674 847502 47460112
MAT_VIEW ACCESS STORAGE FULL OC_MVT SNAP_UAT_T_MUSTERI 263557 21667104 1126689408
HASH JOIN 27041 847502 88987710
MAT_VIEW ACCESS STORAGE FULL OC_MVT SNAP_UAT_T_CANDIDATE 5059 546527 26779823
TABLE ACCESS STORAGE FULL OC_CST CST_CUSTOMER_INFO 17674 847502 47460112
NESTED LOOPS
NESTED LOOPS 7 2 222
TABLE ACCESS STORAGE FULL OC_CST CST_CUSTOMER_TEMP 3 1 55
INDEX RANGE SCAN OC_CST IDX_OC_CST_CUSTOMER_NBNKCST_NO 2 2
TABLE ACCESS BY INDEX ROWID OC_CST CST_CUSTOMER_INFO 4 2 112
MAT_VIEW ACCESS BY INDEX ROWID OC_MVT SNAP_T_ADRES 2 1 50
INDEX UNIQUE SCAN OC_MVT T_ADRES_CLIENT_NO2 1 1
TABLE ACCESS BY INDEX ROWID OC_CRD CRD_CARD 4 1 89
INDEX RANGE SCAN OC_CRD IDX_CRD_CARD_05 2 1

Edited by: 983327 on Jun 5, 2013 6:23 AM
Jonathan Lewis
983327 wrote:
I'm sending queries and plans. I hope you can und:)it is really long.
As far as I can tell from what you've supplied the difference between the two pieces is that one checks cst.name and the other checks cst.name2; is this correct ?

Since there are three queries it would be good to see three execution plans. Convention dictates that you use dbms_xplan to generate the plans so that we get a standard format; and if you include the code tags (the word code in curly brackets) before and after the output it will be presented in fixed to preserve space.

As it is, I'd be interested to know what predicate is associated with the FILTER operation neat the top of the second part of the UNION plan.

If you want to return the correct results for your query, you may need to go back to a UNION ALL, and add a predicate to the second half to exclude rows where cst.name is like '%ASDF%' - taking care that you don't lose rows where the name is null.

A first thought is that you may have uncovered an Oracle bug which has resulted in a calculation from the second part of the query being transferred into the calculations for the first part of the query - changing the cardinalities dramatically, hence the execution plan. This MIGHT be something to do with the statistics of name2 - for example, if a large percentage of the customer rows are null in that column. Without predicate information and the individual plan for the second part of the query, though, I wouldn't like to speculate any further.


UPDATE: I've changed my mind about a switch in cardinality across the two parts of the UNION. The cardinalities match up. The interesting thing is that the cost (or, at least, the column I think is the cost) for the bit you showed us has the following figures for SNAP_UAT_T_CANDIDATE:

Single query:
       MAT_VIEW ACCESS BY INDEX ROWID	OC_MVT	SNAP_UAT_T_CANDIDATE	26817	27326	1338974
        INDEX FULL SCAN	OC_SYS	IX2_CANDIDATE_NAME	1354	27326	
UNION query
        MAT_VIEW ACCESS STORAGE FULL  OC_MVT  SNAP_UAT_T_CANDIDATE  5058  27326  1338974
A cost of 5058 for the tablescan and a cost o 26817 for the indexed access path.
At first sight, the tablescan should have been the first choice in both cases.


I think I've got it - you've got a load of hints in the two separate queries. As with most hinted SQL the hinting is probably very bad, but it produces a "good enough" effect when the queries are run individually - even though it forces the optimizer into a couple of INDEX FULL SCAN steps. When you introduce a UNION, there are a load of changes to query block names, and some of your hints are therefore directed to the wrong place and are irrelevant - and you get parts of the plan with lower costs but (presumably, since you're asking) higher run times.



Regards
Jonathan Lewis

Edited by: Jonathan Lewis on Jun 5, 2013 6:06 PM

Edited by: Jonathan Lewis on Jun 5, 2013 6:11 PM
User505978 - Oracle
**At first, thank you so much Jonathan, for your detailed answer and opinions. You asked me for the 3rd execution plan, i und what you mean but you can count it is same with the other individual query's sql_plan.
**yes , the only difference is name and name2 columns but there are indexes for both columnns for both MWs.

I'm aware i added many hints but the cst_customer views include 3 different views and those views are using materalized views. I had to use QB_NAME to give specific hints for each nested views.

Also i tested index full scan and table scan, though full scan shows better costs, index full scan has much more better run times. I think obsolete statics can be the reason for this.
Jonathan Lewis
983327 wrote:
**At first, thank you so much Jonathan, for your detailed answer and opinions. You asked me for the 3rd execution plan, i und what you mean but you can count it is same with the other individual query's sql_plan.
**yes , the only difference is name and name2 columns but there are indexes for both columnns for both MWs.

I'm aware i added many hints but the cst_customer views include 3 different views and those views are using materalized views. I had to use QB_NAME to give specific hints for each nested views.

Also i tested index full scan and table scan, though full scan shows better costs, index full scan has much more better run times. I think obsolete statics can be the reason for this.
Your original question was: "I have two queries which use plan X when I run them separately but do something completely different when I stick them together with a UNION". My point about the hints and the degree to which your hints are correct or not was that the UNION introduces a new level of query blocks, and your hints (or some of them) have therefore (probably) gone out of scope and are no longer addressing the query blocks that they need to address. In other words, the new plan may well be the plan that you would get if you deleted all the hints.

Regards
Jonathan Lewis
User505978 - Oracle
I want to ask sth lastly.

I know that there is "baseline" with 11g insted of outlines in 10g. I tested baseline on my local database but it is not enough to solve my problem.

For example;

I create baseline for the following sql before creating index;

select name from emp where emp_id=123;

i checked it is using full table scan.

Then i create an index for the table and when i query same sql, it is not using index according to created baseline. Everything is ok till here.

But, when i change my sql like this:

select name from emp where emp_id=234;

it is using the index. I'm aware that sql is changed and baseline is not referenced for this query.


My question is:

is there anyway to force this query not to use index with different emp_id?
unknown-7404
>
My question is:

is there anyway to force this query not to use index with different emp_id?
>
Since that is a new question you need to create a new thread.
1 - 13
Locked Post
New comments cannot be posted to this locked post.

Post Details

Locked on Apr 7 2017
Added on Mar 6 2017
38 comments
9,559 views