Sorry for shouting .. but
Nag, August 25, 2002 - 7:32 pm UTC
I have no control over how users insert.. what I want to see is how I can convert
select to_char( x, 'mm/dd/yyyy' ) from t; into a date with the date format mm/dd/yyyy
is that possible ?
August 25, 2002 - 9:21 pm UTC
I told you how. alter session. See also
</code>
http://asktom.oracle.com/Misc/NLSDateFormat.html <code>
there you go -- and guess what, you DO in fact have control over how they insert -- as their inserts will NOT work in any arbitrary format (and lack of access is the ultimate in control). Hence, they will either need to alter session (bad idea) OR they will need to say what they mean (always a good idea)
Clarification
Nasser, February 08, 2003 - 4:26 pm UTC
Tom
So if the Nls_date_format is set to 'dd-mon-yy' , not matter how you enter the date it will insert it in the same format i.e. dd-mon-yy..
Is that what you are tryig to say.. I have tested this as below..
SQL> create table t( x date);
Table created.
SQL> insert into t values(sysdate);
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t;
X
---------
08-FEB-03
SQL> insert into t values(to_date('02/08/2003', 'mm/dd/yyyy') );
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t;
X
---------
08-FEB-03
08-FEB-03
SQL> insert into t values(to_date('2003/02/07','yyyy/mm/dd'));
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t;
X
---------
08-FEB-03
08-FEB-03
07-FEB-03
So now if I want to start storing the date in my datbase in 'yyyy/mm/dd' format then I should set my nls_date format to 'yyyy/mm/dd.
February 08, 2003 - 4:43 pm UTC
No, not at all:
<quote>
A date is stored in an internal 7 byte format that the machine likes to use
(bits and bytes).
For us poor humans, who cannot read the bits and bytes -- we have date formats.
The formats are EDITS applied to the bits and bytes that convert them from the
internal format (a DATE) to a string so we can read them.
</quote from above...>
the format string is just an edit, just an edit -- a format, nothing more, nothing less.
the date always has century, year, month, day, hour, minute, second -- regardless of the format used to insert it or retrieve it.
Got you...
Nasser, February 08, 2003 - 5:02 pm UTC
SQL> alter session set nls_date_format='yyyy-mm-dd' ;
Session altered.
SQL> select * from t;
X
----------
2003-02-08
2003-02-08
2003-02-07
insert into t values(to_date('02/08/2003', 'mm/dd/yyyy') );
SQL> select * from t;
X
----------
2003-02-08
2003-02-08
2003-02-07
2003-02-08
How can I know the nls_date_format of our database?
7 byte format
Nasser, February 08, 2003 - 5:10 pm UTC
Tom
SQL> select length('dd-mon-yyyy') from dual;
LENGTH('DD-MON-YYYY')
---------------------
11
A dates internal format should take 11 bytes. How come according to you it is only 7 bytes...
What is the format which enables storage of date in 7 bytes, please give insight into it...
7 bytes
Tony Andrews, February 08, 2003 - 6:11 pm UTC
Nasser, that's really funny! But you could have gone further:
SQL> select to_char( sysdate,'DAY DD MONTH YYYY HH:MM:SSAM') from dual
2 /
TO_CHAR(SYSDATE,'DAYDDMONTHYYYYHH:MM:S
--------------------------------------
SATURDAY 08 FEBRUARY 2003 11:02:27PM
SQL> select length(to_char( sysdate,'DAY DD MONTH YYYY HH:MM:SSAM')) from dual
2 /
LENGTH(TO_CHAR(SYSDATE,'DAYDDMONTHYYYYHH:MM:SSAM'))
---------------------------------------------------
38
And it STILL fits into 7 bytes!!! I guess that's the difference between INTERNAL formats and EXTERNAL formats for you!
Dear Tony
Nasser, February 08, 2003 - 7:21 pm UTC
My question in brief was...
What is the internal format in which the date is stored? and I was just giving an example.
Full Format
LakshmiNarasimhan, February 09, 2003 - 1:53 am UTC
I believe Oracle will store every portion of date ,
The Year (Full year)
Month
Date
Time (AM / PM indicator or 24 hours format)
Am I rigt Tom?
Regards
Date format
Tony Andrews, February 09, 2003 - 5:43 am UTC
Nasser,
Sorry my previous answer was a little "tongue in cheek"!
Oracle DATE columns are stored internally as the number of seconds since some date way in the past. We have 7 bytes to store it in - how big is that?
1 byte = 8 bits. This can store numeric values up to (2**8)-1 = 255
7 bytes = 56 bits. This can store numeric values up to (2**56)-1 = 7.2058E+16, i.e. 72,058,000,000,000,000
That is the number of different DATE values, in seconds, there can be. How many years is that?
7.2058E+16 / 60 / 60 / 24 / 365 = 2,284,931,318
i.e. 2 billion years.
So with a 7-byte DATE column you could in theory record any date and time (to the second) from around 1 billion BC to around 1 billion AD.
I'm not saying that's EXACTLY how Oracle dates work, but it is similar, and shows how they could easily accomodate all the dates you'll ever need in 7 bytes or less.
February 09, 2003 - 3:15 pm UTC
Helena Markova, February 10, 2003 - 4:58 am UTC
Get ready all you consultants!!!
John, February 10, 2003 - 12:52 pm UTC
The year 2000 problem WILL happen again and we'll call it the year 4712 problem.
Date format chaning query results
A reader, September 11, 2003 - 4:54 pm UTC
The date format 'MM RRRR' is returning wrong results where as 'RRRRMM' returning the correct
data. Can you please explain as to why this is happening. Is there a more efficient way of doing the date comparision for the given case.
SQL> DESC TEST;
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER
BEGIN_DT DATE
END_DT DATE
VOL NUMBER
SQL> SELECT * FROM TEST;
ID BEGIN_DT END_DT VOL
---------- --------- --------- ----------
1 26-FEB-03 31-DEC-03
2 01-JAN-03 31-DEC-07 100
3 01-JAN-03 31-DEC-03 3
4 01-JAN-04 31-DEC-08 400
5 01-JAN-03 31-DEC-04 80
6 01-JAN-05 31-DEC-14 1000
7 01-MAY-03 30-SEP-03 100
7 rows selected.
SQL> select *
2 from TEST
3 where TO_CHAR(BEGIN_dT,'MM RRRR') <= TO_CHAR(SYSDATE, 'MM RRRR')
4 and TO_CHAR(end_dT,'MM RRRR') >= TO_CHAR(SYSDATE, 'MM RRRR')
5 /
ID BEGIN_DT END_DT VOL
---------- --------- --------- ----------
1 26-FEB-03 31-DEC-03
2 01-JAN-03 31-DEC-07 100
3 01-JAN-03 31-DEC-03 3
4 01-JAN-04 31-DEC-08 400
5 01-JAN-03 31-DEC-04 80
6 01-JAN-05 31-DEC-14 1000
7 01-MAY-03 30-SEP-03 100
7 rows selected.
SQL> select *
2 from TEST
3 where TO_CHAR(BEGIN_dT,'RRRRMM') <= TO_CHAR(SYSDATE, 'RRRRMM')
4 and TO_CHAR(end_dT,'RRRRMM') >= TO_CHAR(SYSDATE, 'RRRRMM')
5 /
ID BEGIN_DT END_DT VOL
---------- --------- --------- ----------
1 26-FEB-03 31-DEC-03
2 01-JAN-03 31-DEC-07 100
3 01-JAN-03 31-DEC-03 3
5 01-JAN-03 31-DEC-04 80
7 01-MAY-03 30-SEP-03 100
September 11, 2003 - 7:54 pm UTC
it is giving you 110% what you asked for.
think about it.
think "strings"
you do not have dates -- you have two strings.
tell me, which is "bigger"
12 xxxx
01 xxxx
??? hmmm, now what about
12 1902
01 2001
which is bigger? (same answer, they are STRINGS not dates!!!!!)
you have nice DATES!!! why -- why -- why would you convert them into strings?!?!
where begin_dt < add_months(trunc(sysdate,'mm'),1)
and end_dt >= trunc(sysdate,'mm')
that is what you want.
give me everything where the begin_date happens this month and before AND end_date is in this month or later.
Strange behaviour while converting to date !!!
Shailendra, July 20, 2004 - 11:44 am UTC
Hi Tom,
We have observed a very strange behaviour while converting text to Date in a view and then selecting from it. Hope you would be able to throw some light on it as we are clueless.
Following is a Copy/paste from the SQL Plus window. The database version is 8.1.7
SQL*Plus: Release 8.0.5.0.0 - Production on Tue Jul 20 16:29:2 2004
(c) Copyright 1998 Oracle Corporation. All rights reserved.
Connected to:
Oracle8i Enterprise Edition Release 8.1.7.3.0 - Production
With the Partitioning option
JServer Release 8.1.7.3.0 - Production
SQL> variable MON_TXT varchar2(8);
SQL> exec :MON_TXT := 'FEB-2004';
PL/SQL procedure successfully completed.
SQL> SELECT * FROM
2 (
3 SELECT
4 TO_DATE(MONTH,'MON-YYYY') COL_TIME
5 FROM
6 (
7 SELECT 'JAN-2004' MONTH FROM DUAL
8 UNION ALL
9 SELECT 'FEB-2004' MONTH FROM DUAL
10 )
11 )
12 WHERE COL_TIME = TO_DATE(:MON_TXT, 'MON-YYYY');
no rows selected
SQL> exec :MON_TXT := 'JAN-2004';
PL/SQL procedure successfully completed.
SQL> /
COL_TIME
---------
01-FEB-04
01-JAN-04
SQL>
The section where you see the text
----------------
7 SELECT 'JAN-2004' MONTH FROM DUAL
8 UNION ALL
9 SELECT 'FEB-2004' MONTH FROM DUAL
----------------
I have put for simulation purposes but the actual business data is obtained via csv files which are loaded into db using SQL Loader. The business data is very similar to the simulated data the only difference being few extra columns present in business data like fact and dimensions which are irrelevant for current problem.
Thanks for you help,
Shailendra
July 20, 2004 - 8:29 pm UTC
you are not clueless, it is definitely doing the wrong thing (does not reproduce in 9ir2 btw).
workaround appears to be:
12 WHERE COL_TIME = (select TO_DATE(:MON_TXT, 'MON-YYYY') from dual);
I reproduced in 817 your issue. Please contact support a file a bug with your very simple, clear test case.
Thanks very much
Shailendra, July 21, 2004 - 7:07 am UTC
Hi Tom,
Hmm interesting !
How does the "work around" work then? What change does it make to the query plan(as the queries are same semantically)?
I did some investigation on query plans and found that the introduction of select from dual forces a join/filter on the resultset , instead of individual filters which were happening before. But not sure hence the question. Below are the explain plan of the two statements:
SQL> variable MON_TXT varchar2(8);
SQL> exec :MON_TXT := 'JAN-2004';
PL/SQL procedure successfully completed.
SQL> SELECT * FROM
2 (
3 SELECT
4 TO_DATE(MONTH,'MON-YYYY') COL_TIME
5 FROM
6 (
7 SELECT 'JAN-2004' MONTH FROM DUAL
8 UNION ALL
9 SELECT 'FEB-2004' MONTH FROM DUAL
10 )
11 )
12 WHERE COL_TIME = TO_DATE(:MON_TXT, 'MON-YYYY');
COL_TIME
---------
01-JAN-04
01-FEB-04
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 VIEW
2 1 UNION-ALL
3 2 FILTER
4 3 TABLE ACCESS (FULL) OF 'DUAL'
5 2 FILTER
6 5 TABLE ACCESS (FULL) OF 'DUAL'
SQL> SELECT * FROM
2 (
3 SELECT
4 TO_DATE(MONTH,'MON-YYYY') COL_TIME
5 FROM
6 (
7 SELECT 'JAN-2004' MONTH FROM DUAL
8 UNION ALL
9 SELECT 'FEB-2004' MONTH FROM DUAL
10 )
11 )
12 WHERE COL_TIME = (SELECT TO_DATE(:MON_TXT, 'MON-YYYY') FROM DUAL);
COL_TIME
---------
01-JAN-04
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 FILTER
2 1 VIEW
3 2 UNION-ALL
4 3 TABLE ACCESS (FULL) OF 'DUAL'
5 3 TABLE ACCESS (FULL) OF 'DUAL'
6 1 TABLE ACCESS (FULL) OF 'DUAL'
Thanks,
Shailendra
July 21, 2004 - 8:36 am UTC
it is a bug -- please file one with support. You can use the workaround as a "workaround", for unless this was already bugged (support is best to do the research on this), it take some amount of time to fix it (and you probably don't want to wait). Also, they will fix it in 8174 -- not 8173.
(workaround works by preventing the pushing of the predicate)