Date Query
Munzer, February 23, 2002 - 5:24 pm UTC
Tom:
1. I do not understand why i have to use to_Date is SQL book says that between should find dates min>=date<=max.
SInce I am passing those as parameters from a web page, how can is use the time in to_date fucntion with the parameter
where date between to_date(p_fromdate,23:59:59) and to_Date(p_todate,23:59:59)
2. if you use bind variables like you say
where dt_col between to_date( :bv1, 'dd-mon-yyyy' )
and to_date( :bv2, 'dd-mon-yyyy' ) + (1-1/24/60/60)
WHERE DO YOU bind variables and what do you use. owa_util.bind_variables
3. I do not undesrtand how going from stateless web app to stateful does not make a differene in speed. On one app I noticed big difference since i am only using one connection rather than connectio per page.
THe app has 100 procedures but packages are not used. DO you think grouping those procedures into packages by functional area would spped the page loading. IT is taking about 5-6 seconds to run the page now.
Thank you,
February 23, 2002 - 6:20 pm UTC
1) you dont HAVE to use to_date -- I am strongly ENCOURAGING you to use to_date to avoid ambiguities (compare strings to strings, numbers to numbers, dates to dates -- don't RISK confusion comparing strings to numbers, dates to strings).
Always use YYYY formats as well!!!
Now as for: "SQL book says that between should find dates min>=date<=max." -- I tried to tell you -- IT IS DOING just that!!
It is because
17-jan-02 is really January 17th, 2002 at 0 hundred hours (eg: an hour before 1am on jan 17th).
Therefore, only dates in your database that are LESS THAN or EQUAL to January 17th, 2002 at 0 hundred hours would be returned. You wanted ALL dates between 0 hundred hours January 1st, 2002 and MIDNIGHT January 17th, 2002 -- hence you need to use a date that is MIDNIGHT January 17th, 2002 (well, really 23:59:59 on January 17th, 2002)....
with the p_fromdate and p_todate -- if the contents of those PLSQL variables is 01-jan-02 and 17-jan-02 (and I would BEG you to alter your interface to make it be 2002, not 02!) then you would code:
where date between to_date( p_fromdate, 'dd-mon-yy' )
and to_date( p_todate, 'dd-mon-yy' ) + (1-1/24/60/60)
that gets you from january 1st, 2002 at 0 hundred hours to midnight on january 17th, 2002.
2) yes, you would use owa_util.bind_variables if you are using owa_util.list_print/cells_print
3) Then on that app, the pages must have been very very fast and the connection was a large portion of the total request time (or for some reason the connection was taking much longer then it should).
If it is taking 5-6 seconds to run a page -- you have SLOW sql and/or SLOW PLSQL code. Using dbms_profiler and/or tkprof (start with tkprof) you will find out which it is. 5-6 seconds indicates your application itself is slow, not the connection (a connection should take a small fraction of a second).
As for packages -- another suggestion I have is that all REAL production code would use NOTHING other then packages and would never use a stand alone function. See </code>
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:286816015990 <code>
for why. So yes, put EVERYTHING into packages. EVERYTHING.
date query
Munz, February 23, 2002 - 10:37 pm UTC
Tom:
if you are designing a screen and prompting the user to enter dates how would you prompot them to enter format:
DD-MON-YY or
DD-MON-YYYY or
DD/MM/YYYY or
MM/DD/YYYY or
DD/MM/YY or
MM/DD/YY
I am sure user does not like to enter YYYY for year.
How does oracle store date format?
Can you take the user format and re-format it and store it in oracle's format
February 24, 2002 - 9:28 am UTC
The above things are STRINGS, they are not dates. They are strings that can be converted into dates.
Maybe in your application, if someone enters
01-jan-30
01-jan-99
it is clear what that means. Depending on your default NLS_DATE_FORMAT that will either be:
01-jan-2030
01-jan-2099
OR
01-jan-2030
01-jan-1999
ambiguities like that scare the $#@ out of me. If you are going to allow them to enter
dd-mon-YY
then you better use a DATE format in your TO_DATE to avoid all ambiguities. I would suggest using
to_date( string, 'dd-mon-RR' )
and learn what the different between RR and YY is (see the SQL reference manual under date formats). In that scenario, no matter what database you install your code into - you KNOW whats going to happen. I don't like to rely on defaults, be explicit.
Best would be to have some javascript that as you TABBED out of the date field, it would REWRITE the date from dd-mon-yy into dd-mon-yyyy (your java script would look at the input, see if only two digits were supplied and supply the other two). In that fashion the end user need not supply the century but they will SEE the century that will be used -- giving them the opportunity to overwrite that with the correct century when needed.
v$session
Munz, February 27, 2002 - 2:04 pm UTC
Tom:
Which column(s) in v$session tells you whether you have stateful or stateless environment.
I did a select on the table but could not figure it out
February 27, 2002 - 3:50 pm UTC
none really. "stateful" and "stateless" is a WEB concept, done at the app server layer.
If you see lots of connected but "idle" sessions -- and the usernames correspond to the usernames of your web applications, then you probably have stateful.
select username, status from v$session where username is not null;
VL, February 27, 2002 - 9:20 pm UTC
Select * from table
where date >= to_date('20020101', 'YYYYMMDD')
and date < to_date('20010117', 'YYYYMMDD') + 1
February 28, 2002 - 10:05 am UTC
variation on a theme. same thing as the between does yes.
Stuart, February 28, 2002 - 12:30 pm UTC
I've also used + .99999 (5 nines) which appears to set the time to 23:59:59 - I find this a wee bit easier to remember than (1-1/24/60/60)!
ie
where date between to_date( p_fromdate, 'dd-mon-yy' )
and to_date( p_todate, 'dd-mon-yy' ) + .99999
February 28, 2002 - 1:22 pm UTC
Depends on how you think I guess. I'm trained to see:
1-1/24/60/60
and think that's 1 day minus 1 second. I see it so often -- that .99999 would confuse the heck out of me. I'm so used to adding an hour (1/24) or a minute (1/24/60) or so on -- that I always use that. Even when asked to add 4 hours 20 minutes, i'll code:
4*(1/24) + 20*(1/24/60)
Does this means all Dates in April ...?
Pascal, April 29, 2002 - 6:11 am UTC
Hi Tom,
Using your logic i note that my query is using the Index and is very fast...
select count(*) from my_big_table
where idx_date_col
between to_date('01.04.2002' , 'DD.MM.YYYY') and
last_day(to_date('04.2002' ,'MM.YYYY') ) + 1 - 1/24*60*60) ;
I want to use that to get all records in April , 2002 .
Do you think it's correct ?
Thanks
April 29, 2002 - 7:44 am UTC
Nope:
1 select
2 (last_day(to_date('04.2002' ,'MM.YYYY') ) + 1 - 1/24*60*60)
3* from dual
ops$tkyte@ORA817DEV.US.ORACLE.COM> /
(LAST_DAY(TO_DATE('0
--------------------
02-dec-2001 00:00:00
this:
1 select
2 (last_day(to_date('04.2002' ,'MM.YYYY') ) + 1 - 1/24/60/60)
3* from dual
ops$tkyte@ORA817DEV.US.ORACLE.COM> /
(LAST_DAY(TO_DATE('0
--------------------
30-apr-2002 23:59:59
is what you want (/60/60 NOT *60*60)
Sorry , I forgot the ( Bracket there)
Pascal, April 29, 2002 - 8:00 am UTC
Hi Tom ,
Thanks for your prompt reply ,
Sorry i forgot the Left Bracket in the Denominator :
It should have been :
select last_day(to_date('04.2002' ,'MM.YYYY') ) + 1 -
1/(24*60*60) from dual;
April 29, 2002 - 8:46 am UTC
That is correct then.
Stateless vs Statefull
Johan Snyman, April 30, 2002 - 10:46 am UTC
Wouldn't connection pooling done by modplsql also result in connected but idle sessions with the web app's usernames in v$session, regardless of stateless or statefull configuration ?
One could look in the DAD configuration file (if using modplsql) and look at the stateful = setting (No for stateless, Yes for stateful), or alternatively look at the setting via the DAD admin URL (which we have completely disabled for security reasons).
The file is in $ORACLE_HOME/Apache/modplsql/cfg
Or DAD setting have stateful = No and v$session filtered for session with the appserver machine field looks like this:
select sid,serial#,username,status,server from v$session where machine = 'e250';
SID SERIAL# USERNAME STATUS SERVER
32 22027 HENDRIKAB INACTIVE DEDICATED
33 55660 ALLASTAIRH INACTIVE DEDICATED
34 41854 HENDRIKAB INACTIVE DEDICATED
38 43595 HENDRIKAB INACTIVE DEDICATED
49 56163 HENDRIKAB INACTIVE DEDICATED
58 28926 HENDRIKAB INACTIVE DEDICATED
65 9406 HENDRIKAB INACTIVE DEDICATED
79 47751 HENDRIKAB INACTIVE DEDICATED
As you can see, the same user doesn't always pick up the same session, but if someone else login via the web app, one of the idle entries just get replaced, e.g.:
select sid,serial#,username,status,server from v$session where machine = 'e250';
SID SERIAL# USERNAME STATUS SERVER
32 22027 HENDRIKAB INACTIVE DEDICATED
33 55660 ALLASTAIRH INACTIVE DEDICATED
34 41856 JOHANS INACTIVE DEDICATED
38 43595 HENDRIKAB INACTIVE DEDICATED
49 56163 HENDRIKAB INACTIVE DEDICATED
58 28926 HENDRIKAB INACTIVE DEDICATED
65 9406 HENDRIKAB INACTIVE DEDICATED
79 47751 HENDRIKAB INACTIVE DEDICATED
Therefore, queries on v$session definitely doesn't decisively indicate stateless or statefull operation. As far as I can see, one would have to look at the config file, or maybe you'll have to look at v$session over time after changing to statefull and verify that the sid/serial#/USERNAME combination never change for the login in question, or maybe start more statefull connections than what is available in the pool (I haven't tested what happens in that case - our test environment is not online at the moment).
April 30, 2002 - 11:46 am UTC
You are correct. I never use (or even consider using) "stateful" connections myself.
Yes, v$session won't tell you if it is stateless or stateful.
Still wondering about some of this
Bill Bunke, May 21, 2002 - 11:06 am UTC
First of all, your two rules cannot be said often enough. Thanks for emphasizing them! (I am also surprised that we did not truly learn our lesson from y2k.)
Regarding date ranges: I too have had to deal with this type of question from colleagues. My answer varies slightly in that I feel uncomfortable in hard-coding the last possible moment in the day (1 second before midnight currently).
With the addition of timestamps in 9i, I can foresee where they will become universal in date-time usages, and I don't rule out the possibility that their granularity may find its way into date typed values (and shouldn't we all be encouraging code that avoids possible future problems?!).
Because of those reasons, I've always recommended the following approach for date ranges (to select inclusive dates from Jan 1st 2002 to Jan 17th 2002):
WHERE 1=1
AND dt_col BETWEEN TO_DATE('01-jan-2002','dd-mon-yyyy')
AND TO_DATE('17-jan-2002','dd-mon-yyyy')+1
AND dt_col <> TO_DATE('17-jan-2002','dd-mon-yyyy')
This to me is a universal definition of inclusiveness for dates (in the generic sense, including DATE and TIMESTAMP data formats).
It might be worth considering having a LAST_TIME built-in function developed, that returned the last possible date-time value for the date parameter passed, since this scenario is so prevalent (after all, LAST_DAY as a built-in is not really needed [it is the same as TRUNC (ADD_MONTHS(your_date,1) , 'MON')-1].
Thanks.
May 21, 2002 - 12:15 pm UTC
That'll work -- that is true, with the TIMESTAMP type in 9i -- the 23:59:59 would miss 25:59:59.99999
Why so much trouble?
Kim Berg Hansen, May 22, 2002 - 7:54 am UTC
Followup to Bill's review.
This seems a bit excessive to me :
AND dt_col BETWEEN TO_DATE('01-jan-2002','dd-mon-yyyy')
AND TO_DATE('17-jan-2002','dd-mon-yyyy')+1
AND dt_col <> TO_DATE('17-jan-2002','dd-mon-yyyy')
I would have used :
AND dt_col >= TO_DATE('01-jan-2002','dd-mon-yyyy')
AND dt_col < TO_DATE('17-jan-2002','dd-mon-yyyy')+1
But since all you big brains seems to want to use BETWEEN - I wonder if there's a reason for that ?
Does the optimizer work better with BETWEEN than my way of doing it ?
Regards
Kim Berg Hansen
Senior Systems Engineer
T.Hansen Group
Denmark
May 22, 2002 - 8:25 am UTC
Well -- on the "big brains" comment -- we are all just people. He saw my idea, saw the flaw (one second won't work in 9i with a timestamp type!) and corrected it. You just refined it -- that makes you a big brain too I guess!
That works as well -- very well and it is more terse. The other (with the between) seems to "say more" to me (when reading it) however the <> part does tend to confuse it for other readers.
Thanks for the followup.
Does Trunc will stop the index
Yamani, May 22, 2002 - 9:57 am UTC
For the example above :
where dt_col between to_date( '01-jan-2002 00:00:00', 'dd-mon-yyyy hh24:mi:ss' )
and to_date( '17-jan-2002 23:59:59', 'dd-mon-yyyy hh24:mi:ss' )
Can't we use TRUNC instead:
AND TRUNC(dt_col) >= TO_DATE('01-jan-2002','dd-mon-yyyy')
AND TRUNC(dt_col) < TO_DATE('17-jan-2002','dd-mon-yyyy')
Is this have any problem with Index.
Thanks,
May 22, 2002 - 10:46 pm UTC
unless you have an index on TRUNC(dt_col) -- yes, using trunc on dt_col would obviate an index on dt_col.
followup to Bill's review
A reader, May 23, 2002 - 1:07 pm UTC
shouldn't the statement
WHERE 1=1
AND dt_col BETWEEN TO_DATE('01-jan-2002','dd-mon-yyyy')
AND TO_DATE('17-jan-2002','dd-mon-yyyy')+1
AND dt_col <> TO_DATE('17-jan-2002','dd-mon-yyyy')
be
WHERE 1=1
AND dt_col BETWEEN TO_DATE('01-jan-2002','dd-mon-yyyy')
AND TO_DATE('17-jan-2002','dd-mon-yyyy')+1
AND dt_col <> TO_DATE('18-jan-2002','dd-mon-yyyy')
Bill's followup to A Readers followup
Bill Bunke, May 28, 2002 - 1:24 pm UTC
Yes, there was a typo in the sample code snippet posted; however, your fix, although accurate, would not be the syntax of choice. Introducing another data value (which of course would be actually handled by a host variable) is not efficient; all you want or need to have are the two dates signifying the beg/end you are interested in.
Here is an amended snippet:
WHERE 1=1
AND dt_col BETWEEN TO_DATE(:v_beg_dt,'dd-mon-yyyy')
AND TO_DATE(:v_end_dt,'dd-mon-yyyy')+1
AND dt_col <> TO_DATE(:v_end_dt,'dd-mon-yyyy')+1
-- where :v_beg_dt = '01-JAN-2002'
-- and :v_end_dt = '17-JAN-2002'
-- or some other values (perhaps parameter driven)
Taking others comments into account, I still think Oracle should provide an End-of-Day functionality, either with a LAST_TIME function or perhaps an EOD format suffix (adds last possible time component to supplied date).
Thanks for your comments.
To_date PROBLEM
atul, August 16, 2002 - 1:23 am UTC
Sir,
I have a query like..
SELECT A.DIV_CD,D.DIV_DESc
FROM TEST1 A,TEST2 B WHERE TO_DATE(RCIA_DT)=TO_DATE(:b1)AND ("SOME MORE STATEMENTS")
now because of TO_DATE(RCIA_DT)=TO_DATE(:b1) it's doing full table scan so how to avoid that full table scan??
Thanks.
atul
August 16, 2002 - 7:35 am UTC
Sounds like RCIA_DT is a string then (else why would you to_date a date right)
So, if RCIA_DT is a string, just use "where rcia_dt = :b1 and ...."
QED
If rcia_dt is in fact a date, lose the to_date (cause you could easily corrupt a date by using to_date on it!)
Consider this (and think through WHY it is happening, hint, my NLS_DATE_FORMAT is dd-mon-rr)
ops$tkyte@ORA817DEV.US.ORACLE.COM> create table t ( x date );
Table created.
ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM> insert into t values ( to_date( '01-jan-1904', 'dd-mon-yyyy' ) );
1 row created.
ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM> select x, to_date(x), to_date(x) - x, to_char(to_date(x),'dd-mon-yyyy')
2 from t;
X TO_DATE(X TO_DATE(X)-X TO_CHAR(TO_
--------- --------- ------------ -----------
01-JAN-04 01-JAN-04 36525 01-jan-2004
ops$tkyte@ORA817DEV.US.ORACLE.COM>
to_date(x) is not equal to x if X is a date in this example!!!
date insert
mo, January 09, 2003 - 10:30 am UTC
Tom:
if you have a html form where you prompt for an "effective date" and that is also part of the primary key in the table, oracle inserts the data with 00:00:00 timestamp which creates a problem in validating primary key.
SO I want to insert the date with the time the user entered with it:
Would you do insert into table(data) values
(to_Date(p_date)||to_char(sysdate,'hh24:mi:ss') )
OR you would add the time from 00:00:00 to current system time to the date.
How do you convert the current time to number and add it to date with 00:00:00 timestamp.
2. is there a way to update a timestamp for a date in the database?
Thank you,
January 09, 2003 - 1:30 pm UTC
why that would "create a problem in validating primary key" is way beyond my understanding.
Why would you add the rather RANDOM string of digits that happen to be the current hour, minute, second? Why not just use 00:00:00 (midnight)? It is as VALID AS ANY OTHER TIME OF THE DAY is it not????
I would use 00:00:00 and figure out why I did wrong in my model that I felt compelled to add a random number to my date to "fix a validation problem"
update updates data -- yes. just update the data???
another query
PK, January 09, 2003 - 3:36 pm UTC
I have a table which has column declared as varchar2.
Date is stored in that field. Why ? Its existing system so I
can't ask it.
Coming to my concern, Now the people have realised there mistake want to correct the data. So, is there a way I can get only the correct date fields and avoid the other records ?
here is sample data from the table :-
PK>select * from temp1;
ID
----------------------------------------------------------------------------------------------------
2002-01-01
2002-01-23
2002-13-01
2002-12-31
2002-12-34
200 -12-01
002-12 01
02- 1- 1
2002 01 01
2002- 4-01
2002-12- 9
11 rows selected.
Elapsed: 00:00:00.80
I have written something like this
PK>l
1 select to_date(id,'yyyy-mm-dd') from temp1
2 where length(id) = 10
3 and length(ltrim(rtrim(substr(id,1,4)))) = 4
4 and substr(id,5,1) = '-'
5 and substr(id,8,1) = '-'
6 and sign(substr(id,6,2) - 12) < 1
7* and sign(substr(id,9,2) - 31) < 1
PK>/
TO_DATE(I
---------
01-JAN-02
23-JAN-02
31-DEC-02
01-APR-02
09-DEC-02
5 rows selected.
Elapsed: 00:00:00.40
PK>
IS there a better way ?
Thanks
PK
January 09, 2003 - 6:19 pm UTC
You can:
create or replace function my_to_date( p_string in varchar2 ) return date
as
begin
return to_date( p_string, 'yyyy-mm-dd' );
exception
when others then return null;
end;
instead -- then
select my_to_date( id ) from temp1;
Wrong result set
PK, January 10, 2003 - 2:16 pm UTC
Thanks for the immediate response.
But when I'm using the function I see some discrepancy :-
HEre is the data from the table
PK>select * from temp1;
ID
----------------------------------
2002-01-01
2002-01-23
2002-13-01
2002-12-31
2002-12-34
200 -12-01
002-12 01
02- 1- 1
2002 01 01
2002- 4-01
2002-12- 9
2003-10-10
12 rows selected.
Elapsed: 00:00:00.10
The blanks are null.
PK>l
1 CREATE OR REPLACE FUNCTION MY_to_Date
2 (v_inp_str IN VARCHAR2)
3 RETURN date IS
4 BEGIN
5
6 RETURN to_date(v_inp_str,'YYYY-MM-DD');
7 EXCEPTION
8 WHEN OTHERS THEN
9 return NULL ;
10* END;
PK>/
Function created.
Elapsed: 00:00:00.60
PK>
PK>select my_to_date( id ) from temp1;
MY_TO_DAT
---------
01-JAN-02
23-JAN-02
31-DEC-02
01-DEC-00
01-DEC-02
01-JAN-02
01-JAN-02
01-APR-02
09-DEC-02
10-OCT-03
12 rows selected.
Elapsed: 00:00:00.50
PK>
There are blank lines in between thats fine but I have a question regarding the number of columns returned .
PK>select to_char(my_to_date(id),'dd-mon-yyyy') from temp1;
TO_CHAR(MY_
-----------
01-jan-2002
23-jan-2002
31-dec-2002
01-dec-0200
01-dec-0002
01-jan-0002
01-jan-2002
01-apr-2002
09-dec-2002
10-oct-2003
12 rows selected.
Elapsed: 00:00:00.70
Why are the null spaces treated as zeros ??
Thanks in advance.
January 10, 2003 - 2:30 pm UTC
null spaces are not null spaces. they are blanks.
put whatever logic you need into my_to_date to make it work for you.
like , =
umesh, February 21, 2003 - 7:47 am UTC
1 select to_date ( hiredate,'dd-mon-yyyy:hh24-mi-ss') from emp
2 where to_date(hiredate,'dd-mon-yyyy:hh24-mi-ss') +1 =
3* to_date('24-JAN-1982:12-00-00','dd-mon-yyyy:hh24-mi-ss')
SQL> /
no rows selected
1 select to_date ( hiredate,'dd-mon-yyyy:hh24-mi-ss') from emp
2 where to_date(hiredate,'dd-mon-yyyy:hh24-mi-ss') +1 like
3* to_date('24-JAN-1982:12-00-00','dd-mon-yyyy:hh24-mi-ss')
SQL> /
TO_DATE(H
---------
23-JAN-82
February 21, 2003 - 10:23 am UTC
what is your point? you get what you ask for.
your default date format is apparently dd-mon-yy or maybe rr.
to_date(hiredate,'dd-mon-yyyy:hh24-mi-ss')
is really:
to_date( TO_CHAR(hiredate,'dd-mon-yy'), 'dd-mon-yyyy:hh24-mi-ss' )
there are soooo many things wrong with these two queries -- where to begin....
a) first you are using to_date on a column that is ALREADY A DATE. That means hiredate is turned into a string using the default format (dd-mon-rr) and then converted back into a date -- and you used YYYY sooooo guess what year that hiredate is??? 1982 or 2082 or maybe even something more bizzare?? Watch:
scott@ORA920> select to_date(hiredate,'dd-mon-yyyy:hh24-mi-ss'),
2 to_char(to_date(hiredate,'dd-mon-yyyy:hh24-mi-ss'),'yyyy'),
3 to_char(hiredate,'yyyy')
4 from emp
5 /
TO_DATE(H TO_C TO_C
--------- ---- ----
17-DEC-80 0080 1980
20-FEB-81 0081 1981
22-FEB-81 0081 1981
02-APR-81 0081 1981
28-SEP-81 0081 1981
01-MAY-81 0081 1981
09-JUN-81 0081 1981
09-DEC-82 0082 1982
17-NOV-81 0081 1981
08-SEP-81 0081 1981
12-JAN-83 0083 1983
03-DEC-81 0081 1981
03-DEC-81 0081 1981
23-JAN-82 0082 1982
14 rows selected.
so,
rule number 1 -- beware of IMPLICIT CONVERSIONS OF DATES and NUMBERS!!!
rule number 2 -- never to_number a number, never to_date a date
b) in the second query you make the same mistake as the first but get unintentially "lucky". LIKE works on strings -- sooooo that predicate is "where string like string". Soooo there is yet another implicit conversion, there are to_char's wrapped about those to_dates:
select to_date ( hiredate,'dd-mon-yyyy:hh24-mi-ss')
from emp
where TO_CHAR(to_date(hiredate,'dd-mon-yyyy:hh24-mi-ss') +1) like
TO_CHAR(to_date('24-JAN-1982:12-00-00','dd-mon-yyyy:hh24-mi-ss'))
/
so, yes, when you COMPARE the strings:
23-JAN-82 with 23-JAN-82
they are "like" eachother. However, if you looked at the REAL DATES -- you see that you just had a hit on
23-jan-0082 with 23-JAN-1982
eg: you got the wrong answer in general.
sooo
rule number 3, compare dates to dates, strings to strings, numbers to numbers and never anything other combination
rule number 4, always be on the lookout for implicit conversions. You have 6 of them in your two queries. They are the cause of all of your problems
date = date character like character
umesh, February 23, 2003 - 10:59 pm UTC
Thank you Tom. I learn something daily from you
problems with date?
Alejandro Berrones Cruz, March 07, 2003 - 4:15 pm UTC
I did a SQL like this
select empleid, emple
from emp
where hiredate = to_date('05/03/2003','dd/mm/yyyy')
But there are not records... I have 10 records with that hiredate in emp table
I´m using Oracle 9i.... and the hiredate field is a date type
March 07, 2003 - 6:20 pm UTC
no, you don't. Plain and simple, you do not have 10 records with that date.
select to_date( hiredate, 'mm/dd/yyyy hh24:mi:ss' ) from emp
where to_char(hiredate,'mm/dd/yyyy') = '05/03/2003';
report back what THAT says.
Date conversion.
A Reader, May 30, 2003 - 11:48 am UTC
Hi Tom,
Do we have a function or way to format the date difference to "dd hh24:mi:ss" format? For example, after minus date2 from from date1, we get 0.25. Can we convert it into '6:00:00'?
Thank you for your help.
Interval Arithmatic on systimestamp?
jochuan, August 07, 2003 - 1:43 pm UTC
Tom
I changed the datatype of datetime columns in my batch_log table (BATCH_LOG.START_DATETIME and BATCH_LOG.END_DATETIME) from sysdate to systimestamp to get more detailed time information.
I used to be able to do
select batch_type
, avg(end_datetime-start_datetime)
, max(end_datetime-start_datetime)
, min(end_datetime-start_datetime)
group by batch_type
now with the systimestamp data type, I cannot do avg() or any aggregrate functions because it errors out
0RA-00932: INCONSISTENT DATATYPES: expected NUMBER got INTERVAL
In this case, is there a way to do interval arithmatic like I used to do?(does not seem to be supported in the manual)
Thanks so much!
August 09, 2003 - 5:38 pm UTC
you would have to implement a user defined aggregate right now.
here is a simple sum
create or replace type day_to_second_sum_type as object
(
total interval day to second,
static function
ODCIAggregateInitialize(sctx IN OUT day_to_second_sum_type )
return number,
member function
ODCIAggregateIterate(self IN OUT day_to_second_sum_type ,
value IN interval day to second )
return number,
member function
ODCIAggregateTerminate(self IN day_to_second_sum_type,
returnValue OUT interval day to second,
flags IN number)
return number,
member function
ODCIAggregateMerge(self IN OUT day_to_second_sum_type,
ctx2 IN day_to_second_sum_type)
return number
);
/
create or replace type body day_to_second_sum_type
is
static function ODCIAggregateInitialize(sctx IN OUT day_to_second_sum_type)
return number
is
begin
sctx := day_to_second_sum_type( numtodsinterval( 0, 'SECOND' ) );
return ODCIConst.Success;
end;
member function ODCIAggregateIterate(self IN OUT day_to_second_sum_type,
value IN interval day to second )
return number
is
begin
self.total := self.total + value;
return ODCIConst.Success;
end;
member function ODCIAggregateTerminate(self IN day_to_second_sum_type,
returnValue OUT interval day to second,
flags IN number)
return number
is
begin
returnValue := self.total;
return ODCIConst.Success;
end;
member function ODCIAggregateMerge(self IN OUT day_to_second_sum_type,
ctx2 IN day_to_second_sum_type)
return number
is
begin
self.total := self.total + ctx2.total;
return ODCIConst.Success;
end;
end;
/
CREATE or replace
FUNCTION ds_sum(input interval day to second )
RETURN interval day to second
PARALLEL_ENABLE AGGREGATE USING day_to_second_sum_type;
/
reader, August 28, 2003 - 12:19 pm UTC
Tom,
I need to get the past 12 months information (begining from current month), I used the following query, I felt not safety. Because the 2002 i_date might be 0002 or 2002 , so I can not get the correct result. Can you have a good idea ?
SELECT I_DATE FROM T
WHERE
TO_CHAR(ADD_MONTHS(sysdate,-11),'YYYYMM') < TO_CHAR(I_DATE,'YYYYMM') AND
TO_CHAR(I,'YYYYMM') <= TO_CHAR(sysdate,'YYYYMM');
Thank you!
August 29, 2003 - 7:48 am UTC
umm, and exactly why might the i_date be in the year "2"????
select i_date
from t
where i_date >= add_months(sysdate,12);
would be the most appropriate way to do that and if you actually have dates with the year "2" in them -- you need to *fix* that data. it is obviously wrong.
comparing time...
A reader, March 19, 2004 - 7:44 am UTC
Hi TOM,
I have a confusion regarding cmparing of time.
Say we have a table sdheduler with columns
locations varchar(20)
,batchstarttime date
,batchnumber number
and we have data like
LOCATIONS BATCHSTARTTIME BATCHNUMBER
-------- -------------- ------------
DO 01-JAN-2000 23:15 1
DO 01-JAN-2000 09:15 2
DO 01-JAN-2000 09:12 3
DO 30-DEC-1999 10:00 4
CO 01-JAN-2000 08:15 85
CO 01-JAN-2000 13:15 89
FO 30-DEC-1999 11:00 6
GO 30-DEC-1999 05:00 7
GO 30-DEC-1999 10:10 77
HO 30-DEC-1999 04:00 8
HO 30-DEC-1999 07:00 9
HO 30-DEC-1899 09:00 10
HO 01-JAN-2000 10:30 78
now i want to find out the batchnumber which ran just before 11:00 Hrs at any day for different locations
like from the above data i should get
DO 30-DEC-1999 10:00 4
CO 01-JAN-2000 08:15 85
GO 30-DEC-1999 10:10 7
HO 01-JAN-2000 10:30 78
How do i do this ?
i have been trying something like
SELECT a.locations, a.batchstarttime, a.batchnumber
FROM scheduler a
WHERE TO_CHAR (TO_DATE ('19-MAR-2004 11:00', 'DD-MON-YYYY hh24:mi'),
'hh24:mi'
) >
(SELECT MAX (TO_CHAR (b.batchstarttime, 'hh24:mi'))
FROM scheduler b
WHERE a.batchnumber = b.batchnumber AND a.LOCATION = b.locations)
how do i do this ? Please help.
Regards
March 19, 2004 - 9:54 am UTC
you can use this technique (object_id = batch_number, object_name = locations, created = batchstartime
ops$tkyte@ORA9IR2> select object_id, object_name, to_char(created,'dd-mon-yyyy hh24:mi') created
2 from (
3 select object_id, object_name, max(created)
over (partition by trunc(created)) max_created, created
4 from all_objects
5 where to_char( created, 'hh24' ) < '11'
6 )
7 where created = max_created
8 order by created
9 /
OBJECT_ID OBJECT_NAME CREATED
---------- ------------------------------ -----------------
30772 ALL_PARAMETERS 01-dec-2003 10:21
31367 TMP 02-jan-2004 09:31
34892 MYCTX 11-feb-2004 09:15
33923 T 15-jan-2004 09:05
34117 LOAD_TEST_DATA 16-jan-2004 06:42
35557 OP 17-mar-2004 08:28
35783 FTP 18-mar-2004 10:57
35797 EMP 19-mar-2004 09:14
34288 BONUS 20-jan-2004 06:31
34286 EMP 20-jan-2004 06:31
34289 SALGRADE 20-jan-2004 06:31
34290 DUMMY 20-jan-2004 06:31
34287 DEPT 20-jan-2004 06:31
30492 UTL_RECOMP_INV_IDX1 25-nov-2003 09:04
34562 MY_FILES 28-jan-2004 07:40
15 rows selected.
Or:
ops$tkyte@ORA9IR2> select object_id, object_name, to_char(created,'dd-mon-yyyy hh24:mi') created
2 from all_objects x
3 where to_char( created, 'hh24' ) < '11'
4 and created = ( select max(created)
5 from all_objects
6 where trunc(created) = trunc(x.created)
7 and to_char(created,'hh24') < '11')
8 order by created
9 /
OBJECT_ID OBJECT_NAME CREATED
---------- ------------------------------ -----------------
30772 ALL_PARAMETERS 01-dec-2003 10:21
31367 TMP 02-jan-2004 09:31
34892 MYCTX 11-feb-2004 09:15
33923 T 15-jan-2004 09:05
34117 LOAD_TEST_DATA 16-jan-2004 06:42
35557 OP 17-mar-2004 08:28
35783 FTP 18-mar-2004 10:57
35797 EMP 19-mar-2004 09:14
34288 BONUS 20-jan-2004 06:31
34287 DEPT 20-jan-2004 06:31
34290 DUMMY 20-jan-2004 06:31
34286 EMP 20-jan-2004 06:31
34289 SALGRADE 20-jan-2004 06:31
30492 UTL_RECOMP_INV_IDX1 25-nov-2003 09:04
34562 MY_FILES 28-jan-2004 07:40
15 rows selected.
but you'll find the first one to be "better" i believe.
A reader, March 19, 2004 - 7:46 am UTC
sorry there was a typo in the above query....
SELECT a.locations, a.batchstarttime, a.batchnumber
FROM scheduler a
WHERE TO_CHAR (TO_DATE ('19-MAR-2004 11:00', 'DD-MON-YYYY hh24:mi'),
'hh24:mi'
) >
(SELECT MAX (TO_CHAR (b.batchstarttime, 'hh24:mi'))
FROM scheduler b
WHERE a.batchnumber = b.batchnumber AND a.locations = b.locations)
installation
haron, March 19, 2004 - 1:27 pm UTC
Please help me how can i install oracle 8i and 8 and forms in windows xp millions of thanks i need your responds thanks
Thanks for the query
A reader, March 20, 2004 - 6:08 am UTC
Thanks a lot TOM....
ANY IDEAS ABOUT DOING THIS TOM
LOU, July 27, 2004 - 6:21 pm UTC
a procedure where I can put something like this
01/01/2004 23:59:59
add 01/01/2004 00:00:01
and get 01/01/2004 24:00:01
and then 01/01/2004 00:00:00
and then get 01/01/2004 00:00:01
Thanks Tom
July 27, 2004 - 7:49 pm UTC
see the other place you asked the same exact thing.
Thanks Tom
Lou, July 28, 2004 - 9:36 am UTC
Sometime I get irrational demands. My manager thought
we could do the following
7/28/2004 9:00:00 AM display this
and then add 7/28/2004 9:00:01 AM
and see the result ???
July 28, 2004 - 1:05 pm UTC
ask the manager to add january 1st to january 15th, I'd be interested in the answer :)
Using between for date queries
Dave, November 10, 2004 - 11:25 am UTC
Tom,
I have a query having one of the where condition as :
date_issued between to_date('01/01/2004','mm/dd/yyyy') and sysdate
I see a bad performance when I run the query with the above condition. Is there any other/better way to deal with dates in long running queries? I tried "and" instead of between and the performance was further bad. The best I could get was using between but wanted to check if any other way exists.
FYI, I have an index on date_issued column.
Thanks for all your help.
November 10, 2004 - 12:25 pm UTC
totally insufficient information here.
I see really good performance, i used EMP though :)
Dave, November 10, 2004 - 12:34 pm UTC
I even tried something like this:
select count(*) from (
<< here goes the fast running sql >>
)
where date_issued between to_date('01/01/2004','mm/dd/yyyy') and sysdate;
I thought since the subquery runs first and returns less than 200 rows, the date checking would be faster for 200 rows. But this too did not help.
How should I proceed??? :(
November 10, 2004 - 2:32 pm UTC
who said the subquery "runs first"
you have given me virtually nothing to work with here.
Few more info about the above sql
A reader, November 10, 2004 - 12:51 pm UTC
Tom, here is the trace plan that I ran, if at all it helps.
SQL> set autotrace on
SQL> SELECT count(*)
2 FROM activity
3 WHERE contact_id = 192271;
COUNT(*)
----------
129
1 row selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=4)
1 0 SORT (AGGREGATE)
2 1 INDEX (RANGE SCAN) OF 'IX_ACTIVITY_1' (NON-UNIQUE)(Cost=3 Card=30 Bytes=120)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
2 physical reads
0 redo size
368 bytes sent via SQL*Net to client
153 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> SELECT count(*)
2 FROM activity
3 WHERE contact_id = 192271
4 and completed_date
5 BETWEEN to_date('01-Mar-2004','dd-mon-yyyy')
6 AND to_Date('30-Nov-2004','dd-mon-yyyy');
COUNT(*)
----------
50
1 row selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=12 Card=1 Bytes=11)
1 0 SORT (AGGREGATE)
2 1 BITMAP CONVERSION (COUNT)
3 2 BITMAP AND
4 3 BITMAP CONVERSION (FROM ROWIDS)
5 4 INDEX (RANGE SCAN) OF 'IX_ACTIVITY_1' (NON-UNIQUE)(Cost=4)
6 3 BITMAP CONVERSION (FROM ROWIDS)
7 6 SORT (ORDER BY)
8 7 INDEX (RANGE SCAN) OF 'IX_ACTIVITY_3' (NON-UNIQUE)(Cost=8)
Statistics
----------------------------------------------------------
20570 recursive calls
7623 db block gets
14380 consistent gets
26775 physical reads
479136 redo size
368 bytes sent via SQL*Net to client
445 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
1 sorts (disk)
1 rows processed
SQL>
November 10, 2004 - 2:33 pm UTC
how do you gather statistics. *exact*, *precise* command
and, are they up to do.
bitmap access plan ...
Gabe, November 10, 2004 - 3:54 pm UTC
Regarding the previous post ...
The ACTIVITY table probably has a bitmap index on it (likely on something other than ACTIVITY_ID or COMPLETED_DATE) ... if this the case (and this is an OLTP environment) consider removing it or replace it with a regular index. Goes w/o saying that stats should be up-to-date regardless.
date range query
mo, December 09, 2004 - 7:01 pm UTC
Tom:
I have a table that includes two fields:
Invoice_Month Varchar2(10),
Invoice_FY number(4)
First field is the month the invoice was for, and the second is the year the month the invoice for.
I need to create a report that allows a user to report on records for a given date range like (Jan 2003 - March 2004).
1. Can I write a SQL statement that queries the string using "between" like
"give me all records where invoice_month between "jan" and "marc" and invoice_fy between "2003" and "2004"?
2. If you were designing this would you change the type of Invoice_month to a number and a do range check on the number?
Thank you,
December 10, 2004 - 1:00 am UTC
too bad the designers of this system made simple things soooooo hard.
a date is a date
a string is a string
a string isn't a date.
sigh.
they have convienently made this pretty much impossible to do efficiently - without a function based index (if you feel an index would be right)
create index date_idx on t( to_date( Invoice_month || ' ' || invoice_fy, 'Mon yyyy' ) );
where to_date( .... ) >= :bv1 and to_date( .... ) < add_months(:bv2,1);
2) not a chance --those two fields a DATE COLUMN -- period, they are not two fields AT ALL, they are a DATE!
date range query
mo, December 13, 2004 - 11:07 am UTC
Tom:
Well the requirement was to track the month and year for what the invoice was for.
You can receive an invoice dated "05-DEC-2004" where this is stored in invoice_date. However the person sending the invoice has to specify that this invoice was for work completed in the month of "June" and "2004" Fiscal Year.
However, I think storing a number for the month and year would solve this problem. Then we can do
select * from table where invoice_month between 1 and 3 and invoice_fy between 2004 and 2004.
Do you see any potential problems with that?
December 13, 2004 - 1:47 pm UTC
"Well the requirement was to track the month and year for what the invoice was
for."
and that is what a date does. 01-dec-2004 -- month = dec, year = 2004.
do i see a problem with your last thing -- umm, yup, huge. Your original question was:
(Jan 2003 - March 2004).
Ok, so tell me -- in two fields -- how do you do that one nicely??? :)
this is a DATE
sure, you could use a single 6 digit number:
YYYYMM
but even that implementation is horribly flawed as it includes NO EDITING that the date is valid and it HIDES information from the optimizer.
You have a DATE.
mo, December 13, 2004 - 7:31 pm UTC
Tom:
I am confused. What is the problem with this solution?
Invoice_Month Number(2),
Invoice_FY number(4),
Invoice_date date,
Query: What invoices have been billed for January 2003 and March 2004?
Answer:
select * from table where invoice_month between 1 and 3 and invoice_fy between
2003 and 2004.
Please note invoice date is the actual date on the invoice but it could be for some work completed 6 months ago.
December 13, 2004 - 7:37 pm UTC
i think you meant to say
Query: What invoices have been billed BETWEEN January 2003 and March 2004?
but even if not, your answer is wrong (for your original query and the one I assume you mean)
and you get......
jan 2003
feb 2003
mar 2003
jan 2004
feb 2004
mar 2004
think about it...... what about july 2003? month = 7, 7 is NOT between 1 and 3.
You would have to say:
where (year = 2003)
or (year = 2004 and month between 1 and 3)
to paraphrase an old but popular commercial
"dude, you gotta get a DATE field"
http://asktom.oracle.com/~tkyte/Misc/DateDiff.html has a bug
Vladimir Andreev, December 14, 2004 - 8:02 am UTC
Hi Tom,
I thought you'd want to know that there's a bug in the sample query in </code>
http://asktom.oracle.com/~tkyte/Misc/DateDiff.html <code>
In
select to_char( created, 'dd-mon-yyyy hh24:mi:ss' ),
trunc( sysdate-created ) "Dy",
trunc( mod( (sysdate-created)*24, 24 ) ) "Hr",
trunc( mod( (sysdate-created)*24*60, 60 ) ) "Mi",
trunc( mod( (d1-d2)*24*60*60, 60 ) ) "Sec",
to_char( sysdate, 'dd-mon-yyyy hh24:mi:ss' ),
sysdate-created "Tdy",
(sysdate-created)*24 "Thr",
(sysdate-created)*24*60 "Tmi",
(sysdate-created)*24*60*60 "Tsec"
from all_users
where rownum < 50
/
the line
trunc( mod( (d1-d2)*24*60*60, 60 ) ) "Sec",
should probably read
trunc( mod( (sysdate-created)*24*60*60, 60 ) ) "Sec",
.
Cheers,
Flado
December 14, 2004 - 9:07 am UTC
thanks!
date range query
mo, December 14, 2004 - 3:33 pm UTC
Tom:
You are very correct. I combined the two fields into one field of type date and I am storing the first day of the month as part of the date.
Thank you,
Alex, May 13, 2005 - 9:08 am UTC
Hi Tom,
I have a problem in some code that is not returning the information it should and I'm not sure why. But I almost certain the developer who wrote this code didn't compare the dates correctly, here's a the sample:
SQL> CREATE TABLE t (comp_date DATE, file_num VARCHAR(13), id_num NUMBER, comp_oid NUMBER);
Table created.
SQL> insert into t values(to_date('6/1/2005', 'MM/DD/YYYY'), null, '1', '50');
1 row created.
SQL> SELECT comp_oid
2 FROM t
3 WHERE NVL (comp_date, TO_DATE ('01/01/1900', 'MM/DD/YYYY')) =
4 TO_DATE (NVL ('6/1/2005', '01/01/1900'), 'MM/DD/YYYY')
5 AND file_num = NULL
6 AND id_num = '1';
no rows selected
SQL> show parameters nls_date_format;
NAME TYPE VALUE
------------------------------------ ------- ------------------------------
nls_date_format string
SQL>
The date values never equal so I don't get any results. I think they wrote that code to standardize the date for a basis of comparison.
May 13, 2005 - 10:44 am UTC
and file_num = null
will never
a) be true
b) be false
it will always be
c) i have not any idea if it is true or false
where file_num is NULL
there are SO many things wrong in this tiny example!!!!!! so many!!!
a) and file_num = null
has to be and file_num is null
b) and id_num = '1'
has to be and id_num = :x and a NUMBER type must be bound in!!!, you do not ever compare a number to a string or a string to a number, compare numbers to numbers only.
c) WHERE NVL (comp_date, TO_DATE ('01/01/1900', 'MM/DD/YYYY')) =
TO_DATE (NVL ('6/1/2005', '01/01/1900'), 'MM/DD/YYYY')
should only be
where comp_date = to_date(:x,'mm/dd/yyyy')
Alex, May 13, 2005 - 11:57 am UTC
So the fact that I hardcoded values merly for a test can cause inacurate results? That doesn't sound right.
Also, to clarify, if I have a line like this in a WHERE clause:
WHERE file_num = pfile_num
and pfile_num is a parameter coming in that is null, this query will never return anything?
I'm trying this at the moment but I get an error but I was wondering if this going in the direction you suggested:
SQL> DECLARE
2 v_comp_date DATE := TO_DATE ('6/1/2005', 'MM/DD/YYYY');
3 v_file_num VARCHAR (13) := NULL;
4 v_id_num NUMBER := '1';
5 v_comp_oid NUMBER;
6 BEGIN
7 SELECT comp_oid
8 INTO v_comp_oid
9 FROM t
10 WHERE comp_date = TO_DATE (v_comp_date, 'MM/DD/YYYY')
11 AND file_num = v_file_num
12 AND id_num = v_id_num;
13 EXCEPTION
14 WHEN NO_DATA_FOUND
15 THEN
16 DBMS_OUTPUT.put_line ('Still got no rows');
17 END;
18 /
DECLARE
*
ERROR at line 1:
ORA-01858: a non-numeric character was found where a numeric was expected
ORA-06512: at line 7
It works in TOAD though, but I know you don't use that.
May 13, 2005 - 12:39 pm UTC
you gave me a query, I commented on said query -- period.
and file_num = NULL
will never ever ever ever work right.
if pfile_num is null, where file_num = pfile_num will not return ANY rows.
this is the wrong way:
v_id_num NUMBER := '1';
please -- numbers to numbers, dates to dates, strings to strings and don't do it any other way!
v_id_num number := 1;
this is *really* wrong:
WHERE comp_date = TO_DATE (v_comp_date, 'MM/DD/YYYY')
v_comp_date is a date!
that is really = to_date( TO_CHAR(v_comp_date), 'MM/DD/YYYY' )
and that is probably the cause of the error.
you take the date in v_comp_date and convert it to a string using the default date mask, probably dd-mon-yyyy
you take that dd-mon-yyyy string and try to convert it back into a date with mm/dd/yyyy
the formats do not MATCH. and error......
you have a date, do not "to_date" a date.
The implicit conversions going on in this code are *scary*. You need to look twice at this
numbers to numbers
dates to dates
strings to strings
beware the implicit conversion.
lose the to_date in the query and it'll run and say "Still go no rows" because of line 11.
and fix line 4
Alex, May 13, 2005 - 3:23 pm UTC
Got it to work thanks. I am curious about one other thing when you said
c) WHERE NVL (comp_date, TO_DATE ('01/01/1900', 'MM/DD/YYYY')) =
TO_DATE (NVL ('6/1/2005', '01/01/1900'), 'MM/DD/YYYY')
should only be
where comp_date = to_date(:x,'mm/dd/yyyy')
I don't see how those can be functionally equivalent
May 13, 2005 - 4:31 pm UTC
if comp_date is null, you return 01/01/1900.
but TO_DATE (NVL ('6/1/2005', '01/01/1900'), 'MM/DD/YYYY') always returns
6/1/2005
so..... given those inputs, they are the same as comp_date = to_date()
Last DML Date
RUMMAN, May 14, 2005 - 5:53 am UTC
Let a table--
my_dates(prev_processing_date date, last_dml_date date);
I need a trigger for this ----
After DML on any table of my_user
the DML date will be inserted in the above table
and
the last stored date from another table needs to be queried and inserted into the above table.
Example :
ROWID PREV_PROCESSING_DATE ---- LAST_DML_DATE
1 12-MAY-05 ----------- 15-MAY-05
2 16-MAY-05 ------------
//DATA OF ROWID 1 MEANS THAT AFTER EXECUTING PROCEDURE THERE IS SOME DML
//DATA OF ROWID 2 MEANS THAT AFTER EXECUTING PROCEDURE THERE IS NO DML
Is it possible??
May 14, 2005 - 9:38 am UTC
just keey the history of when it was last updated and in the report, you can use lag() and lead() to get what you need.
Not following your example entirely, but this is something that should be retrieved during REPORTING, not during transacting.
Alex, May 16, 2005 - 2:15 pm UTC
Tom,
You mentioned the implicit conversions going on a couple posts up. I've been trying to do a little research on this, I want to be able to see how this effects queries. Is there somewhere where this is covered in some detail? I have tried the docs, they were a little helpful. I've been unable to locate anything in your books on this (though I swear I've read about it in there somewhere). I tried a small test myself and saw no difference in stats.
May 16, 2005 - 4:02 pm UTC
create table t ( x varchar2(5) primary key );
insert into t values ( '5' );
select * from t where x = 5;
select * from t where x = '5';
compare the differences.........
when an implicit conversion leads to implicitly applying a function to an indexed column, that index won't be used.
that first query is really
where to_number(x) = 5;
no index on x will be used.
A reader, May 18, 2005 - 12:36 pm UTC
Tom,
Could you clarify if Oracle updates is date/time based on Operating system date? Could we set Oracle date/time thats not dependent on O/S date/time and is it possible?
May 18, 2005 - 12:57 pm UTC
we get time from the Operating system when we need to get the time.
check the OS clock and the time we report goes with it.
Why implicit date conversion fails
Rajeswari, November 23, 2005 - 4:35 am UTC
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.6.0 - 64bit Production
PL/SQL Release 9.2.0.6.0 - Production
CORE 9.2.0.6.0 Production
TNS for HPUX: Version 9.2.0.6.0 - Production
NLSRTL Version 9.2.0.6.0 - Production
SQL> select * from nls_database_parameters where parameter='NLS_DATE_FORMAT';
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_DATE_FORMAT RRRR/MM/DD HH24:MI:SS
SQL> select * from nls_instance_parameters where parameter='NLS_DATE_FORMAT';
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_DATE_FORMAT RRRR/MM/DD HH24:MI:SS
SQL> select XBO_Gsf_time_togmt(to_date('2005/11/21 16:48:56'),240) from dual;
select XBO_Gsf_time_togmt(to_date('2005/11/21 16:48:56'),240) from dual
*
ERROR at line 1:
ORA-01861: literal does not match format string
Function:
CREATE OR REPLACE Function xbo_Gsf_time_togmt(i_date in date,
i_offset in number)
Return date
is
l_date date;
Begin
if i_date is NULL then
return(NULL);
end if;
l_date := i_date + (i_offset/1440);
return(l_date);
EXCEPTION
when invalid_Number then
return( NULL );
when others
then raise;
end xbo_Gsf_time_togmt;
/
Why the imlicit date conversion is not taking place? Please explain
November 23, 2005 - 9:48 am UTC
because the only one that counts is.... your SESSION:
ops$tkyte@ORA10GR2> select * from nls_database_parameters where parameter='NLS_DATE_FORMAT';
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_DATE_FORMAT DD-MON-RR
ops$tkyte@ORA10GR2> select * from nls_instance_parameters where parameter='NLS_DATE_FORMAT';
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_DATE_FORMAT
ops$tkyte@ORA10GR2> select * from nls_session_parameters where parameter='NLS_DATE_FORMAT';
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_DATE_FORMAT dd/mm/yyyy
ops$tkyte@ORA10GR2>
(hint: avoid implict like the plague, explicit is good)
Implicit date conversion
Rajeswari, November 24, 2005 - 5:18 am UTC
Tom, Thanks for the reply. Always I go by explicit conversion but this is existing code in production.
1. Can I able to get the default date format used by oracle for implicit conversion without quering nls_session_parameters. I enabled the trace and tried to find out about default date format used. But I am not able to find date format used for implicit conversion in trace file.
You may surprise why I need it. I will explain in detail below,
Oracle version: 9.2.0.6
JDBC driver version :9.2.0.5
We are calling the below procedure from Java which make use of xbo_Gsf_time_togmt (my previous thread) function. In Java we are not setting any date format. We set the instance and database date format as RRRR/MM/DD HH24:MI:SS. Procedure ran successfully.
Now we updated the JDBC driver to 10.2.0.1 version. Database is still in 9.2.0.6 version.
Same procedure throws "ORA-01861: literal does not match format string" error.
If the trace gives the default date format used while doing implicit date conversion it will be useful. Anyway our dba is contacting oracle support for this JDBC driver issue.
CREATE TABLE XBO_ET_EQUIP
(
LOCATION VARCHAR2(20),
EQUIP_ID VARCHAR2(60),
STATUS CHAR(1),
USER_ID VARCHAR2(30),
LAST_UPDT_DATE DATE,
DUE_DATE DATE,
COMP_DATE DATE
);
INSERT INTO XBO_ET_EQUIP ( LOCATION, EQUIP_ID, STATUS, USER_ID, LAST_UPDT_DATE, DUE_DATE,
COMP_DATE ) VALUES (
'SR74NJ05H00', 'SR74-WHHS3H00', 'I', 'direct', sysdate,sysdate,sysdate-1);
COMMIT;
CREATE OR REPLACE procedure xbo_esp_equip_status(
i_LOCATION in VARCHAR2,
i_EQUIP_ID in VARCHAR2,
i_status in char,
i_comp_DATE in varchar2,
i_USER_ID in VARCHAR2,
i_offset in number
)
as
begin
update xbo_et_equip
set STATUS = i_status,
comp_DATE = DECODE(i_comp_DATE,'?',comp_DATE,XBO_Gsf_time_togmt(i_comp_DATE,i_offset)),
USER_ID = i_USER_ID,
last_updt_date = sysdate + (XBO_GSF_TIME_OFFSET/(24*60))
where location = i_location
and equip_id = i_equip_id
;
EXCEPTION
when others
then raise;
end xbo_esp_equip_status;
/
November 24, 2005 - 8:52 am UTC
seriously doubt a jdbc issue, more likely - the NLS_LANG is being set in the java client environment and therefore:
</code>
http://asktom.oracle.com/Misc/NLSDateFormat.html <code>
but really - it seems since you are in test, you can fix the oversight made by the developers in the last release and have better resulting code as a result!
any trace to get implicit date conversion format
Rajeswari, November 25, 2005 - 12:54 am UTC
Thanks a lot Tom.
I suggested the same to our dba and other decision making people.
</code>
http://asktom.oracle.com/~tkyte/Misc/NLSDateFormat.html <code>
I gone through this link, typically it is happening in Windows client but we are using both client and server as unix.
Can I able to get the default date format used by oracle for implicit conversion without quering nls_session_parameters using any oracle trace.
November 25, 2005 - 10:07 am UTC
you'd have to query it out, it is not in a trace.
Thanks
Rajeswari, November 29, 2005 - 12:13 am UTC
Thanks a lot Tom.
Our DBA people accepted to change the procedure for explicit conversion.
Query by date
cequal, December 19, 2005 - 11:17 am UTC
Thank you very much this qury was very helpful to me in describing how to query a single dable by created_dt
Thanks again
help on a query
vijay, January 19, 2006 - 7:53 am UTC
Hi Tom,
good day to you as always, I need your help on a query I have, I have table in which records for customers are there having different products I need to fetch customers having just two products as below
e.g Table T (customer,product)
1,PRD-3-2
1,PRD-7-1
2,PRD-6-1
2,PRD-3-2
3,PRD-7-1
3,PRD-6-1
I want customer with PRD LIKE PRD-3% AND PRD-6% but no other products in the above e.g. customer 2
January 19, 2006 - 1:23 pm UTC
select customer
from t
where prd like 'PRD-3%' or prd like 'PRD-6%'
having count(distinct substr(prd,1,5) ) = 2
is *likely* it, but you give insufficient data to fully answer. can there be a prd-55-132 and so on. I'm guessing.
TO_DATE(date column)
Partha, January 20, 2006 - 2:52 am UTC
In my htmldb application, my column for start_date was displaying wrong dates when the format was in yyyy/mm/dd.
I had wrongly typed to_date( start_date, 'yyyy/mm/dd') instead of to_char( start_date, 'yyyy/mm/dd' ).
I checked in sql prompt but could not understand why to_date (date column with different format string) gives an unexpected answer; (maybe it is the expected answer, but I couldn't understand why).
SELECT SYSDATE, TO_CHAR(SYSDATE, 'YYYY/MM/DD'), TO_DATE(SYSDATE, 'YYYY/MM/DD'), TO_DATE(SYSDATE, 'RRRR/MM/DD') FROM DUAL ;
1/20/2006 3:33:57 PM 2006/01/20 1/6/0020 1/6/2020
My question: Why is it displaying 2020 or (0020)? Is it really the century part ?
When I try to do
select to_date( to_date('20/01/2006', 'dd/mm/yyyy'), 'RRRR/MM/DD') FROM DUAL ;
it gives an error ora-1858 error (non-numeric character was found where a numeric was expected) what numeric value is expected here ?
January 20, 2006 - 10:21 am UTC
it was NOT displaying the wrong dates.
You had a bug in your developed application that caused you to format data improperly :)
to_date( start_date, 'yyyy/mm/dd' ) is the same as:
to_date( TO_CHAR(start_date), 'yyyy/mm/dd' )
so, what is your DEFAULT DATE FORMAT, you turned a date into a string, then into a date again.
as for the last question - look at your formats. you have dd/mm/yyyy and then you say "please pretend that is rrrr/mm/dd" - how the could that work?
thanks for the answer but my problem stil remains
Vijay, January 24, 2006 - 2:30 am UTC
Hi Tom,
thanks for the answer to my question on PRD LIKE PRD-3% AND PRD-6% and sorry for the data was not sufficient enough for you to understand my question, below i give the data and my question again.
Table T (customer, product) A customer can have multiple products subscribed products have id has PRD-3-1 now the first digit will change and can be 3,6,7 and will not be a double digit I want to retrieve customers having just products with product id as PRD-3% AND PRD-6% i.e all customers having subscribed to just these two product family not the product family of PRD-7.....
for e.g. the data as follows
101 PRD-3-1
101 PRD-6-2
102 PRD-3-1
102 PRD-7-1
103 PRD-3-1
104 PRD-6-1
105 PRD-3-1
105 PRD-7-1
106 PRD-6-1
106 PRD-7-1
the query should return just 101 customer as this customer has only these two produts to his account, please if you can help me on this.
Kind Regards,
Vijay
January 24, 2006 - 8:09 am UTC
where column like 'PRD-3-%' or column like 'PRD-6-%'
is what you are looking for then
Date Questiton
Yoav, February 02, 2006 - 7:34 am UTC
Hi Tom
For some reason i dont understand why i cant display the data in the follwing way:
QTY INSERT_
---------- -------
35 03/2005
43 04/2005
25 05/2005
17 06/2005
20 07/2005
53 08/2005
31 09/2005
38 10/2005
45 11/2005
72 12/2005
76 01/2006
4 02/2006
Would you please explain why ?
Hir is some data:
create table t_test
(qty number,
insert_date date);
insert into t_test values(76, '01-jan-2006');
insert into t_test values(36, '01-feb-2005');
insert into t_test values(4 , '01-feb-2006');
insert into t_test values(35, '01-mar-2005');
insert into t_test values(43, '01-apr-2005');
insert into t_test values(25, '01-may-2005');
insert into t_test values(17, '01-jun-2005');
insert into t_test values(20, '01-jul-2005');
insert into t_test values(53, '01-aug-2005');
insert into t_test values(31, '01-sep-2005');
insert into t_test values(38, '01-oct-2005');
insert into t_test values(45, '01-nov-2005');
insert into t_test values(72, '01-dec-2005');
commit;
select * from t_test;
QTY INSERT_DA
---------- ---------
76 01-JAN-06
36 01-FEB-05
4 01-FEB-06
35 01-MAR-05
43 01-APR-05
25 01-MAY-05
17 01-JUN-05
20 01-JUL-05
53 01-AUG-05
31 01-SEP-05
38 01-OCT-05
45 01-NOV-05
72 01-DEC-05
13 rows selected.
I need to display the data in the following way:
QTY INSERT_
---------- -------
35 03/2005
43 04/2005
25 05/2005
17 06/2005
20 07/2005
53 08/2005
31 09/2005
38 10/2005
45 11/2005
72 12/2005
76 01/2006
4 02/2006
This is the best i could get: (I belive i dont need to use to_char)
select sum(qty) ,to_char(insert_date,'mm/yyyy') insert_date
from t_test
where insert_date between sysdate - 360 and sysdate
group by to_char(insert_date,'mm/yyyy')
order by 2
SUM(QTY) INSERT_
---------- -------
76 01/2006
4 02/2006
35 03/2005
43 04/2005
25 05/2005
17 06/2005
20 07/2005
53 08/2005
31 09/2005
38 10/2005
45 11/2005
72 12/2005
12 rows selected.
February 02, 2006 - 12:05 pm UTC
ops$tkyte@ORA9IR2> select qty, to_char(insert_date,'mm/yyyy')
2 from t_test
3 where insert_date between sysdate - 360 and sysdate
4 order by insert_date;
QTY TO_CHAR
---------- -------
35 03/2005
43 04/2005
25 05/2005
17 06/2005
20 07/2005
53 08/2005
31 09/2005
38 10/2005
45 11/2005
72 12/2005
76 01/2006
4 02/2006
12 rows selected.
How do I do sum() on a date/time interval value?
Andrew Piskorski, February 10, 2006 - 8:42 am UTC
I want to take several date/time interval values and sum them up. Do
I REALLY need define my own special type using ODCIAggregateIterate()
as you do above?? Why doesn't Oracle's sum() function "just work" on
native Oracle interval types?
And since sum() doesn't work on interval types, shouldn't there be
some easy way to cast an interval type to a plain floating point
number measured in seconds, so I can sum up those elapsed times? Yet
cast() doesn't seem to work either.
Is there any robust PL/SQL package available to provide aggregate
functions on interval types?
Some distressing examples:
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options
SQL> select 1 as id ,(interval '0 00:00:01' day to second) as sec from all_tables where rownum <= 3;
ID SEC
---------- --------------------
1 +00 00:00:01.000000
1 +00 00:00:01.000000
1 +00 00:00:01.000000
SQL> select id ,sum(sec) from (
select 1 as id ,(interval '0 00:00:01' day to second) as sec from all_tables where rownum <= 3
) group by id ;
2 3 select id ,sum(sec) from (
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected NUMBER got INTERVAL DAY TO SECOND
SQL> select 1 as id
,cast((interval '0 00:00:01' day to second) as number) as sec
from all_tables where rownum <= 3 ;
2 3 ,cast((interval '0 00:00:01' day to second) as number) as sec
*
ERROR at line 2:
ORA-00932: inconsistent datatypes: expected NUMBER got INTERVAL DAY TO SECOND
SQL> select 1 as id
,cast((interval '0 00:00:01' day to second) as date) as sec
from all_tables where rownum <= 3 ;
2 3 ,cast((interval '0 00:00:01' day to second) as date) as sec
*
ERROR at line 2:
ORA-00932: inconsistent datatypes: expected NUMBER got INTERVAL DAY TO SECOND
February 10, 2006 - 12:59 pm UTC
I cannot answer "why"
I can only say "it does not"
To Andrew
Michel Cadot, February 10, 2006 - 1:30 pm UTC
Here's a workaround:
SQL> select id, sum(sysdate+sec-sysdate)*86400
2 from
3 (select 1 as id ,(interval '0 00:00:01' day to second) as sec from
4 all_tables where rownum <= 3)
5 group by id;
ID SUM(SYSDATE+SEC-SYSDATE)*86400
---------- ------------------------------
1 3
1 row selected.
or to avoid multiple calls to sysdate:
SQL> select id, sum(now+sec-now)*86400
2 from
3 (select 1 as id ,(interval '0 00:00:01' day to second) as sec from
4 all_tables where rownum <= 3),
5 (select sysdate now from dual where rownum<2)
6 group by id;
ID SUM(NOW+SEC-NOW)*86400
---------- ----------------------
1 3
1 row selected.
Regards
Michel
Date Question
Yoav, February 19, 2006 - 8:57 am UTC
Hi Tom,
Regard to the questsion i asked in February 02, 2006 .
I add the following 3 insert:
insert into t_test values(2, '05-jan-2006');
insert into t_test values(3, '06-feb-2005');
insert into t_test values(6 , '07-feb-2006');
Then i query the the table again:
select * from t_test;
QTY INSERT_DA
---------- ---------
76 01-JAN-06
36 01-FEB-05
4 01-FEB-06
35 01-MAR-05
43 01-APR-05
25 01-MAY-05
17 01-JUN-05
20 01-JUL-05
53 01-AUG-05
31 01-SEP-05
38 01-OCT-05
45 01-NOV-05
72 01-DEC-05
Since i want to aggregate the data per month , i used the SUM function
select sum(qty) ,to_char(insert_date,'mm/yyyy') insert_date
from t_test
where insert_date between sysdate - 360 and sysdate
group by to_char(insert_date,'mm/yyyy')
order by 2;
SUM(QTY) INSERT_
---------- -------
76 01/2006
4 02/2006
35 03/2005
43 04/2005
25 05/2005
17 06/2005
20 07/2005
53 08/2005
31 09/2005
38 10/2005
45 11/2005
72 12/2005
12 rows selected.
The problem is that data is not sorted the way i wanted.
You solution wasnt good for me because you didnt used SUM.
Thanks Again.
February 19, 2006 - 9:12 am UTC
you are sorting by a string (again). you are sorting STRINGS not dates.
I sorted a date.
select qty, to_char(insert_date,'mm/yyyy')
from (
select sum(qty) qty, trunc(insert_date,'m') insert_date
from t_test
where insert_date between sysdate - 360 and sysdate
group by trunc(insert_date,'m')
)
order by insert_date;
Why sysdate in dual shows different
Alay, February 21, 2006 - 12:22 am UTC
Hi Tom,
We have solaris server.
when I try to find out sysdate using following query it shows:
SQL> select to_char(sysdate,'DD-MM-YYYY HH24:MM:SS') "Date" from dual;
Date
-------------------
21-02-2006 10:02:26
Immediately after this I am using "date" command to find out system date. It shos:
SQL> !date
Tue Feb 21 10:19:38 IST 2006
Why these two date are different? Does 'dual' not take date from system date?
February 21, 2006 - 7:38 am UTC
date is running on your client, that is your clients PC date.
sysdate is from the server.
What it does ?
Tanmoy Choudhury, May 25, 2006 - 9:21 am UTC
Hi Tom,
I found out the below sql in V$sqlarea.
>>select TRUNC(SYSDATE@!) from dual
2 /
TRUNC(SYSDATE@!
---------------
25-MAY-06
>>
Is there any significance of puting "@!" after sysdate ??
Thanks
Tanmoy
May 25, 2006 - 1:47 pm UTC
just an internal'ism. nothing you would use.
Why Does Explain Plan Change, switching 2 'RR' to 4 'YYYY'dates
JK Purtzer, September 12, 2006 - 2:08 pm UTC
Oracle 9.2.0.7 Solaris, accessed by web client 9.2.0.7 Windows
In Where clause:
OA.CREATE_DATE >= TO_DATE('8/7/06', 'MM/DD/RR') AND
OA.CREATE_DATE < (TO_DATE('8/8/06', 'MM/DD/RR') +1)
results in Cost 15000 in explain plan full table scans
changing to full 4 character year format reduces cost by factor of 15
In Where clause :
OA.CREATE_DATE >= TO_DATE('8/7/2006', 'MM/DD/YYYY') AND
OA.CREATE_DATE < (TO_DATE('8/8/2006', 'MM/DD/YYYY') +1)
Cost 1000 in explain plan index range scans
OA.CREATE_DATE is a DATE datatype default sysdate
NLS_DATE_FORMAT is DD-MON-RR
September 12, 2006 - 5:40 pm UTC
MM/DD/YYYY is a constant
MM/DD/RR is variable
that is why, one is known at parse time definitely, the other one can change at runtime (true, only every 100 years, but it is NOT deterministic)
Question for you, what is this date:
TO_DATE('8/7/06', 'MM/DD/RR')
no matter what you answer, you are wrong, because I'll change "sysdate" and make it different.
the cost is a reflection of the estimated rows flowing out of the step of the plan, if the plans are the "same" steps - they will run at the same speed.
Naive Date Question
A reader, September 14, 2006 - 2:59 pm UTC
My apologies if this seems naive.
I notice a lot of queries in this and other articles about Oracle date data types involve common business questions in which the time portion is not crucial (invoices from January or items shipped on 15-JUN-2006). I borrowed the Apex date picker approach, which TRUNCs the date so you get an easy-to-use DD-MON-YYYY date that makes it accurate to query in the form of:
where invoice_date = to_date(:P2_INVOICE_DATE,'DD-MON-YYYY')
instead of
where invoice_date >= to_date(:P2_INVOICE_DATE,'DD-MON-YYYY') and
invoice_date < to_date(:P2_INVOICE_DATE,'DD-MON-YYYY')+1
Is there anything wrong with creating a trigger on the table to truncate the date? Something like:
CREATE OR REPLACE TRIGGER trunc_invoice_trg
BEFORE INSERT OR UPDATE
ON invoice
FOR EACH ROW
BEGIN
:NEW.invoice_date := TRUNC(:NEW.invoice_date);
END;
This should take care of any inserts or updates using SYSDATE as well as preserving the usefulness of indexes (assuming you don't use function based indexes).
September 14, 2006 - 4:38 pm UTC
if you have a rule that says "invoice date is a date without time" and you believe some applications might put the time in - you can either
a) use the trigger to silently modify what they inserted. I believe this to be a bad idea in practice - I hate it when triggers silently modify my carefully inserted data.
b) use a constraint "check invoice_date = trunc(invoice_date)" to enforce your business rule and have the errant applications do the right thing.
Changing Date from one country to the other
Phillip Sangha, February 15, 2007 - 1:53 pm UTC
Tom,
I have a situation where in the database server is in EST time zone with DATE fields. The date fields are read by a ¿C/C++¿ program and sent over in an xml file to a ¿C/C++¿ program running on DB servers in deferent time zone. For an example a DB server running in Singapore. The remote program needs to insert the date/time into the Singapore database so that their clients see the time in their own time zone.
So the field needs to be stored in Singapore database but with a date/time that is the exact Singapore conversion date of EST date when it was originally created in the EST time zone.
For example, the field was created on Feb 15th 8:00PM which will be Singapore time Feb 16th in the morning. We want to store this converted date/time in the Singapore database.
Could you guide me what could be a the best route to do it and how to do it? meaning, do we have to use TIMEZONE and then use the NEW_TIME and FROM_TZ etc to convert the date? Or maybe altering the database field in the Eastern Time zone to a TIMESTAMP with zone is better (not sure if this is an option for me yet)?
Thanks.
Phillip
Changing Date from one country to the other --any feedback
Phillip Sangha, February 16, 2007 - 12:22 pm UTC
Hi Tom,
Do you have any feedback/recommendation on my original post just above there?
Thanks
Phillip
February 17, 2007 - 11:12 am UTC
i would not use new_time, in 9i and above there is complete timezone support builtin to the timestamp datatype - you should read up on that type.
There is the concept of a database timezone, and a client timezone - that is more likely what you want.
Converting varchar2 to timestamp
A reader, February 24, 2007 - 10:17 am UTC
Hi Tom,
I am receiving a varchar2 field in the format yyyymmddhhmissSSS where hh is in 24 hour format and SSS is in 3 millisecond digits.
I want to store this fields value in a timestamp format into the database.How to go about it?
I have tried following things but without success.
To_Timestamp('20060101010112345','yyyymmddhh24:mi:ss.ff')
To_Timestamp('20060101010112345','yyyymmddhh24:mi:ss.fff')
To_Timestamp('20060101010112345','yyyymmddhh24:mi:ss.ff3')
Thanks in advance.
Regards,
Sourabh S Jain
February 26, 2007 - 1:08 pm UTC
ops$tkyte%ORA10GR2> select
2 To_Timestamp('20060101010112345','yyyymmddhh24missff')
3 from dual;
TO_TIMESTAMP('20060101010112345','YYYYMMDDHH24MISSFF')
---------------------------------------------------------------------------
01-JAN-06 01.01.12.345000000 AM
Why di I get Feb. 30, Feb 31 in a date column?
A reader, March 02, 2007 - 10:52 am UTC
Hi Tom,
When I run a query on a log table like the following:
select to_char(EVENT_DATE, 'YYYY-MM-DD') evt_d1,
to_char(EVENT_DATE, 'YYYY-Mon-DD HH24:MI:SS') evt_d2 from evet_logs
where event_date >= to_date('2007-02-28','YYYY-MM-DD')
and event_date < to_date('2007-03-01','YYYY-MM-DD')
order by evt_d1;
I got results as below. Why Some of the dates are shown as Feb. 29, 30, 31, which do not exist at all? What could be the cause and how can I correct this? Or is there anything wrong with my date format?
Thank you for your help.
EVT_D1 EVT_D2
-------------------- --------------------
2007-02-31 2007-Feb-31 14:55:16
2007-02-31 2007-Feb-31 20:22:45
2007-02-31 2007-Feb-31 20:59:12
2007-02-31 2007-Feb-31 22:44:28
2007-02-31 2007-Feb-31 23:00:50
2007-02-31 2007-Feb-31 22:40:13
2007-02-31 2007-Feb-31 22:30:12
2007-02-31 2007-Feb-31 23:18:43
2007-02-30 2007-Feb-30 16:07:22
2007-02-30 2007-Feb-30 17:00:23
2007-02-29 2007-Feb-29 13:38:29
2007-02-29 2007-Feb-29 16:31:52
2007-02-29 2007-Feb-29 18:35:19
2007-02-29 2007-Feb-29 19:25:23
2007-02-28 2007-Feb-28 00:00:00
March 04, 2007 - 6:17 pm UTC
and what exactly loaded these dates - I'll guess that a custom program did and they used the binary date format (which we just accept the 7 bytes of data from them without checking) and they messed up.
OK
Kumar, April 27, 2007 - 8:09 am UTC
Hi Tom,
The below query is not working.
what can be the reason?
SQL> select sysdate from dual
2 /
SYSDATE
---------
27-APR-07
1 row selected.
SQL> select current_date from dual
2 /
CURRENT_D
---------
27-APR-07
1 row selected.
SQL> create table t(x int)
2 /
Table created.
SQL> select * from obj where created = sysdate
2 /
no rows selected
SQL> select * from obj where created = current_date
2 /
no rows selected
SQL> select * from obj where created = (select sysdate from dual)
2 /
no rows selected
April 27, 2007 - 11:08 am UTC
because time is forever marching on and we are powerless to stop it.
the dates have a time component (hour, minute, second...)
by the time you query using sysdate, the clock has advanced and the created time is not equal to right now.
OK
A reader, May 03, 2007 - 2:47 am UTC
Thanks Tom.
But I am not able to get the result
even when I use the trunc(sysdate) function which removes the time part from sysdate.
How to get the result for this query?
May 03, 2007 - 5:36 pm UTC
You would have to know the time of object creation
and apparently, you do not.
so, you do not have the inputs for this query.
Tell me, why do you need to do this?
OK
A reader, May 04, 2007 - 2:27 am UTC
Hi Tom,
Just a curiosity.
Won't we able to find from data dictionary
what are the tables that have been created on
today or two days back etc. by passing input as sysdate
or sysdate-2 ?
Please let me know how we can do this.
May 04, 2007 - 12:59 pm UTC
sure, you can do that. not by using SYSDATE since that is RIGHT NOW.
but you didn't use sysdate-2, sysdate-2 would give you everything created in the last 48 hours.
Checking the date format
Roy, May 04, 2007 - 11:23 am UTC
Hi Tom,
We need to code a PLSQL function to check if the date format of an input variable of type varchar2 is 'YYYY-MM-DD' or not.
We just thought that we will write this query which if doesn't throw any exception indicates that it is indeed in the desired format.
SELECT TO_DATE(input_variable,'YYYY-MM-DD') FROM dual;
Yes, we know that this has a catch inherently, since if the input is '2007-05-12', then we don't know if the input format is actually 'YYYY-MM-DD' or 'YYYY-DD-MM'.
However, when we run the below query (on PLSQL Developer), we get strange output:
SELECT TO_DATE('04-May-07','YYYY-MM-DD') FROM dual;
Output:
07/05/0004
Why is this so? How do we do what we want to?
Thanks.
May 04, 2007 - 1:23 pm UTC
MM accepts the string MAY
04 when applied to YYYY is the year "4"
07 when applied to DD is the 7th day
it is all 'good'
A reader, May 30, 2007 - 8:55 am UTC
We have a requirement in which user can input some information for a date. Inormation for date will remain same for that date, user can update it but will not have multiple enteries for the same date.
There will be some information which will have multiple enteries in a date. For these multiple enteries within a date user will iput time like (08:20,15:30 etc). There will be two text boxes on input form one for date and one for time. So we will be keeping to columns in table one with date data type and one with varchar2. You suggest mostly that all such information should be stored in date. How we can store this information in date as from front end we will be getting only time portion form user. User will not ready to input date with time on every repeating entry.
May 30, 2007 - 3:43 pm UTC
if you just have "time", the interval datatype pops immediately into mind.
why
tom, July 12, 2007 - 4:50 pm UTC
when i try to run the below block i get less as output why the comparison using the to_char and string is not correct. i guess both will be using ascii internally ?
begin
if to_char(sysdate,'mm/dd/yyyy') < '12/29/2005' then
dbms_output.put_line ( ' less ' );
else
dbms_output.put_line ( ' Not less ' );
end if;
end;
output is
less
July 12, 2007 - 5:12 pm UTC
you are comparing two strings there - yes. that is "obvious"
if we run this on the last day of this year, you'll get " Not less "
ops$tkyte%ORA10GR2> begin
2 if to_char( last_day( add_months(trunc(sysdate,'y'),11) ),'mm/dd/yyyy') < '12/29/2005' then
3 dbms_output.put_line ( ' less ' );
4 else
5 dbms_output.put_line ( ' Not less ' );
6 end if;
7 end;
8 /
Not less
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> select to_char( last_day( add_months(trunc(sysdate,'y'),11) ), 'mm/dd/yyyy') from dual;
TO_CHAR(LA
----------
12/31/2007
ORA 1858
Anto, February 20, 2008 - 6:35 pm UTC
In one of your replies regarding ORa 1858
"
this is the wrong way:
v_id_num NUMBER := '1';
please -- numbers to numbers, dates to dates, strings to strings and don't do it any other way!
v_id_num number := 1;
this is *really* wrong:
WHERE comp_date = TO_DATE (v_comp_date, 'MM/DD/YYYY')
v_comp_date is a date!
that is really = to_date( TO_CHAR(v_comp_date), 'MM/DD/YYYY' )
"
What is wrong with converting a data column or variable again to a date using to_date function ?
What will be the conversion format/mask for the implicit conversion TO_CHAR(v_comp_date) from date to char field ?
anto
February 20, 2008 - 8:49 pm UTC
... What is wrong with converting a data column or variable again to a date using
to_date function ? ....
v_comp_date was ALREADY A DATE
when they did:
to_date( v_comp_date, 'mm/dd/yyyy')
that was REALLY
to_date( to_char(v_comp_date).....
there was the implicit to_char.
so, one wonders... did they really know what they were doing (my gut reaction is "probably not")
... What will be the conversion format/mask for the implicit conversion
TO_CHAR(v_comp_date) from date to char field ? ...
yes, the DEFAULT DATE MASK FOR THE DATABASE/SESSION.
ops$tkyte%ORA11GR1> alter session set nls_date_format = 'DD/MM/YYYY';
Session altered.
ops$tkyte%ORA11GR1> create table t as select to_date( '12-jan-2008', 'dd-mon-yyyy' ) x from dual;
Table created.
ops$tkyte%ORA11GR1> select x, to_date( x, 'mm/dd/yyyy' ) from t;
X TO_DATE(X,
---------- ----------
12/01/2008 01/12/2008
chew on that for a while and decide if implicit conversions and to_date/to_char calls WITHOUT a format are a good thing...
ORA 1858
Anto, February 21, 2008 - 10:17 am UTC
Thanks Tom - just as I had thought
dagstg@STGDEV1> alter session set nls_date_format = 'dd-mon-yyyy';
Session altered.
dagstg@STGDEV1> create table t as select to_date( '12-jan-2008', 'dd-mon-yyyy' ) x from dual;
Table created.
dagstg@STGDEV1> select x, to_date( x, 'mm/dd/yyyy' ) from t;
select x, to_date( x, 'mm/dd/yyyy' ) from t
*
ERROR at line 1:
ORA-01858: a non-numeric character was found where a numeric was expected
dagstg@STGDEV1> edit
Wrote file afiedt.buf
1* select x, to_date( to_char(x,'mm/dd/yyyy'), 'mm/dd/yyyy' ) from t
dagstg@STGDEV1> /
X TO_DATE(TO_
----------- -----------
12-jan-2008 12-jan-2008
Since the to_char conversion mask and to_date conversion mask do not match we get this 1858. So it is better to avoid to_date to date columns/variables
Just wanted to make sure that the implicit to_char was done using the session/db level nls_date_format mask
thanks
Anto
February 21, 2008 - 11:17 am UTC
what I would say is:
a) avoid always ALL IMPLICIT conversions, if you need to turn a string into a number, a number into a string, a date into whatever - be explicit
b) and when you are being explicit using to_date or to_char - USE A FORMAT - never rely on what you think the default format would be
query involving date columns
Harschil Kaparwan, October 21, 2008 - 8:25 am UTC
Hi Tom
Thanks for your time.
Recently while running a query involving date columns we got hit by ORA-07445, we raised the TAR with Oracle and got the resolution as ( Our RDBMS ver 9.2.0.6) :
1.- upgrade to 9.2.0.7 where this bug is solved (but recommend you to upgrade to 9.2.0.8 as this is the final patchset for 9.2 release)
2.- use the following workaround :
alter system set events '38055 trace name context forever, level 1';
alter system set events '10078 trace name context forever, level 1';
alter system flush shared_pool;
3. using TO_DATE with full date format mask for the query :
select count(*) from T where creation_time > '01-MAR-08 00:00:00' and creation_time < '23-JUL-08 00:00:00'
We are yet to try workaround 2 above. Can you please explain by an example thet how by setting trace events:
event 38055 level 1 (disable redundant range predicate removal)
event 10078 level 1 (disable removal of constant predicates)
will disable redundant range predicate /removal of constant predicates.
I hope you will take my question, as i wanted to know "how" setting above trace events will help us.
I understand that user should have used date to date comparision in above query and would have not left it to Oracle to do the implicit conversion.
Kind regards
October 21, 2008 - 3:53 pm UTC
I would go for option #3 myself - it is the right way to do it - never rely on implicit date formats - never.
I don't need an example to explain "how" setting those events will
a) disable redundant range predicate removal
b) disable removal of constant predicates
It is after all - what they do, it is their "definition". You are hitting an optimizer related issue, setting those events disables some features of the optimizer - avoiding the issue you are encountering. That is all.
query involving date columns ...
Manoj, October 21, 2008 - 4:45 pm UTC
Hi Tom
...I would go for option #3 myself - it is the right way to do it - never rely on implicit date formats - never.
You are right. option#3 is best. But that you and me will use but it is very difficult to tell the people to use explicit conversion.
So, we are opting option#2 as well. Because going for option#1 upgrade is not immediately possible.
Does it means that if we use option#2 and *our people* dont use explicit conversion, then we wont get hit by ORA-07445?
Regards
October 22, 2008 - 8:18 am UTC
...but it is very
difficult to tell the people to use explicit conversion.
....
why? Is it hard to tell them to "design"? to do things "right" or "correctly"? To do something obviously intelligent? smart? safe?
I don't get it....
If support says "those two events will work around this issue", it is likely 'true' - however, if you look at those events, they disable features of the optimizer - obviously you should be expecting immediate side effects as this effects everything in the entire system, right away.
query involving date columns ...
Manoj, October 22, 2008 - 11:55 am UTC
Many Thanks Tom for your valuable info.
...
>>but it is very
difficult to tell the people to use explicit conversion.
....
>why? Is it hard to tell them to "design"? to do things "right" or "correctly"? To do something obviously intelligent? smart? safe?
I don't get it....
....
Sorry for not making it clear earlier. You are right that *design* people should do the things "right" or "correctly".
But here *other* people i was refrering to are end users who use SQLPLUS/SQLDeveloper to get the results from the database and thus use their own set of sqls wherein they not use explicit conversion. Though developer would have followed the things to take care date conversion in design.
We got hit by ORA-07445 because one of the *other people* tried to execute the SQL query involving date cols without explicit conversion.
Further,
....If support says "those two events will work around this issue", it is likely 'true' - however, if you look at those events, they disable features of the optimizer - obviously you should be expecting immediate side effects as this effects everything in the entire system, right away.
What should be apparoach to proceed on setting "those two events" then.
We have tested the same in our test environment and ran the same query. Found no problem , so now decided to implement the same in Live.
We have CBO with MODE First_Rows
Regards.
October 22, 2008 - 4:41 pm UTC
... What should be apparoach to proceed on setting "those two events" then. ..
probably the same amount of regression testing you would do with a patch.
... We have tested the same in our test environment and ran the same query. Found
no problem , so now decided to implement the same in Live.
...
I'm not worried about the query you were trying to fix, I'm worried about every other query in the system - this can and will change plans.
When plans change, one of three things happen.....
things go better
things go the same
you can guess this one....
implicit conversion direction
Michal Pravda, March 06, 2009 - 4:05 am UTC
Hello Tom,
I'm stuck with legacy code full of implicit conversions between character types and numbers. That made me investigate rules of implicit conversions by testing and reading conversion matrix in the SQL reference (never needed before, since I use explictit conversion all the time).
I'd like to ask for the reason of Oracle always converting from char to number. I want to understand why Oracle chooses this "unsafe" direction.
You can't convert "Hello world!" to a number. But you can convert whatever number to a string. The only reason which I can think of for not doing it is that converting number to string may not be precise (binary vs decimal issues), but I am not sure whether this is why Oracle doesn't do it.
ps. Enjoy your near stay in our city
March 06, 2009 - 10:29 am UTC
... I want to understand why Oracle chooses this "unsafe" direction. ...
in order to be predicable and deterministic.
In some countries, the number one and one half would be:
1.5
In others,
1,5
You want to get the same answer (or fail - failure is better than wrong answers) everywhere regardless of the NLS settings.
So, converting a number to a string implicitly would be HORRIBLY unsafe - you would get different answers against the same data!!!!!!
Also, if the data is to be considered a number, but is stored in a string, what would happen if the strings contained:
0
0.0
.0
0e1
000.0000000
0
+0
-0
and you had a number with zero in it. You would be expecting all rows, you would get.... one row.
So, it is
a) NLS settings - would result in different answers
b) the fact that there are a LOT of ways to store the number zero in a string, but they are all "zero"
I am bringing my son with me to Praha for the week - really looking forward to it (wish it were warmer ;) )
implicit conversions
Michal Pravda, March 10, 2009 - 10:06 am UTC
Thank you,
I haven't thought it thoroughly enough, have to try harder next time :)
Missing Something Using Between With Dates
Jim, December 03, 2009 - 1:20 pm UTC
Hi Tom
thought i had a handle on the date formatting using BETWEEN
but am missing something. I cannot figure out why I am not getting all my data when using the BETWEEN statement with a date in one particular sql and not the other
Thanks
**************************************************
create table date1
(
col_date date
);
insert into date1 values (to_date('2009/01/01','yyyy/mm/dd'));
insert into date1 values (to_date('2009/02/01','yyyy/mm/dd'));
insert into date1 values (to_date('2009/03/01','yyyy/mm/dd'));
insert into date1 values (to_date('2009/04/01','yyyy/mm/dd'));
insert into date1 values (to_date('2009/05/01','yyyy/mm/dd'));
insert into date1 values (to_date('2009/06/01','yyyy/mm/dd'));
insert into date1 values (to_date('2009/07/01','yyyy/mm/dd'));
insert into date1 values (to_date('2009/08/01','yyyy/mm/dd'));
insert into date1 values (to_date('2009/09/01','yyyy/mm/dd'));
insert into date1 values (to_date('2009/10/01','yyyy/mm/dd'));
insert into date1 values (to_date('2009/11/01','yyyy/mm/dd'));
insert into date1 values (to_date('2009/12/01','yyyy/mm/dd'));
insert into date1 values (to_date('2009/12/01','yyyy/mm/dd'));
insert into date1 values (to_date('2009/12/01','yyyy/mm/dd'));
insert into date1 values (to_date('2009/12/02','yyyy/mm/dd'));
insert into date1 values (to_date('2009/12/02','yyyy/mm/dd'));
insert into date1 values (to_date('2009/12/03','yyyy/mm/dd'));
insert into date1 values (to_date('2009/12/03','yyyy/mm/dd'));
commit;
compute sum of date_count on report
break on col_date on report
================================================================
--yyyy/mm/dd test
select
to_char (col_date,'yyyy/mm/dd') col_date,
count (col_date) date_count
from date1
where col_date BETWEEN TO_DATE ('2009/01/01','yyyy/mm/dd') and TO_DATE ('2009/12/31','yyyy/mm/dd')
group by to_char (col_date,'yyyy/mm/dd')
order by 1;
output:
COL_DATE DATE_COUNT
---------- ----------
2009/01/01 1
2009/02/01 1
2009/03/01 1
2009/04/01 1
2009/05/01 1
2009/06/01 1
2009/07/01 1
2009/08/01 1
2009/09/01 1
2009/10/01 1
2009/11/01 1
2009/12/01 3
2009/12/02 2
2009/12/03 2
********** ----------
sum 18
--yyyy/mm test
select
to_char (col_date,'yyyy/mm') col_date,
count (col_date) date_count
from date1
where col_date BETWEEN TO_DATE ('2009/01','yyyy/mm') and TO_DATE ('2009/12','yyyy/mm')
group by to_char (col_date,'yyyy/mm')
order by 1;
output:
COL_DAT DATE_COUNT
------- ----------
2009/01 1
2009/02 1
2009/03 1
2009/04 1
2009/05 1
2009/06 1
2009/07 1
2009/08 1
2009/09 1
2009/10 1
2009/11 1
2009/12 3
******* ----------
sum 14
Notice there are 4 entries not accounted for here
================================================================
December 04, 2009 - 4:17 pm UTC
to date with yyyy/mm gives you the first DAY of the month.
ops$tkyte%ORA11GR1> select to_date('2009/01','yyyy/mm'), to_date('2009/12','yyyy/mm') from dual;
TO_DATE('2009/01','Y TO_DATE('2009/12','Y
-------------------- --------------------
01-jan-2009 00:00:00 01-dec-2009 00:00:00
if you want everything between jan-1st at 00:00:00 of 2009 through midnight 31-dec 2009 - you woud use either:
where date_col >= TO_DATE ('2009/01','yyyy/mm')
and date_col < add_months( TO_DATE('2009/12','yyyy/mm'), 1 )
(where it is larger than or equal to jan-1st 2009 at 00:00 and less than jan-1st 2010 at 00:00)
or
where date_col between TO_DATE ('2009/01','yyyy/mm')
and add_months( TO_DATE('2009/12','yyyy/mm'), 1 )-1/24/60/60;
I prefer the former
Follow-Up
Jim, December 07, 2010 - 2:30 pm UTC
Hi Tom
I am still having issues with dates
First
I am trying to figure out why the second date example is faster than the first when it looks like the first date example explain plan seems to be better
I am not very good at reading explain plans, so i am going by the times
When I run each example, the second example executes twice as fast as the first (7 minutes compared to 18 minutes)
Second
The amount of data retrieved in example two for 2005 is far greater than the amount of data retrieved in example one so I am not understanding just why
Note: The data did not change while I was running the selects
This is the value for :v_startdate
12:23:44 SQL> select :v_startdate from dual;
:V_STARTDATE
--------------------------------
2005
Any help is greatly appreciated
The only thing I am changing in the sql statemenst is the where clause for a.auditdate
Thanks
Jim
=============================================================
select
c.name group_name,
TO_CHAR (a.auditdate,'yyyy') yeartodate,
COUNT (a.auditdate) livelinklogins,
COUNT (DISTINCT a.performerid) distinctusers
from
dauditnew a,
kuaf b,
kuaf c
where
a.auditstr = 'Login'
and
a.auditdate >= TO_DATE (:v_startdate,'yyyy')
and
a.performerid = b.id
and
b.groupid = :v_groupid
and
b.groupid = c.id
group by
c.name,
TO_CHAR (a.auditdate,'yyyy')
order by
c.name,
TO_CHAR (a.auditdate,'yyyy');
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------
Plan hash value: 3974924054
-------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 27193 | 1513K| | 1937 (1)| 00:00:24 |
| 1 | SORT GROUP BY | | 27193 | 1513K| 1824K| 1937 (1)| 00:00:24 |
|* 2 | HASH JOIN | | 27193 | 1513K| | 1557 (1)| 00:00:19 |
| 3 | NESTED LOOPS | | 126 | 4284 | | 6 (0)| 00:00:01 |
| 4 | TABLE ACCESS BY INDEX ROWID| KUAF | 1 | 24 | | 1 (0)| 00:00:01 |
|* 5 | INDEX UNIQUE SCAN | KUAF_PRIMARY | 1 | | | 1 (0)| 00:00:01 |
| 6 | TABLE ACCESS BY INDEX ROWID| KUAF | 126 | 1260 | | 5 (0)| 00:00:01 |
|* 7 | INDEX RANGE SCAN | KUAF_GROUPID | 126 | | | 1 (0)| 00:00:01 |
| 8 | TABLE ACCESS BY INDEX ROWID | DAUDITNEW | 289K| 6509K| | 1548 (1)| 00:00:19 |
|* 9 | INDEX RANGE SCAN | DAUDITNEW_INDEXDATEEVENT | 52163 | | | 419 (1)| 00:00:06 |
-------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("A"."PERFORMERID"="B"."ID")
5 - access("C"."ID"=TO_NUMBER(:V_GROUPID))
7 - access("B"."GROUPID"=TO_NUMBER(:V_GROUPID))
9 - access("A"."AUDITDATE">=TO_DATE(:V_STARTDATE,'yyyy') AND "A"."AUDITSTR"='Login')
filter("A"."AUDITSTR"='Login')
flush shared pool
initialize variables
execute sql
log out
11:47:00 SQL> select
11:47:00 2 c.name group_name,
11:47:00 3 TO_CHAR (a.auditdate,'yyyy') yeartodate,
11:47:00 4 COUNT (a.auditdate) livelinklogins,
11:47:00 5 COUNT (DISTINCT a.performerid) distinctusers
11:47:00 6 from
11:47:00 7 dauditnew a,
11:47:00 8 kuaf b,
11:47:00 9 kuaf c
11:47:00 10 where
11:47:00 11 a.auditstr = 'Login'
11:47:00 12 and
11:47:00 13 a.auditdate >= TO_DATE (:v_startdate,'yyyy')
11:47:00 14 and
11:47:00 15 a.performerid = b.id
11:47:00 16 and
11:47:00 17 b.groupid = :v_groupid
11:47:00 18 and
11:47:00 19 b.groupid = c.id
11:47:00 20 group by
11:47:00 21 c.name,
11:47:00 22 TO_CHAR (a.auditdate,'yyyy')
11:47:00 23 order by
11:47:00 24 c.name,
11:47:00 25 TO_CHAR (a.auditdate,'yyyy');
Group Year LiveLink Connects Distinct Logins
------------ ---------------- ------------------- ---------------
Admin_GPSW 2005 9,676 322
2006 142,974 518
2007 150,081 592
2008 166,149 848
2009 131,410 926
2010 120,271 944
************ -------------------
sum 720,561
6 rows selected.
12:05:51 SQL>
=============================================================
select
c.name group_name,
TO_CHAR (a.auditdate,'yyyy') yeartodate,
COUNT (a.auditdate) livelinklogins,
COUNT (DISTINCT a.performerid) distinctusers
from
dauditnew a,
kuaf b,
kuaf c
where
a.auditstr = 'Login'
and
TO_CHAR (a.auditdate,'yyyy') >= :v_startdate
and
a.performerid = b.id
and
b.groupid = :v_groupid
and
b.groupid = c.id
group by
c.name,
TO_CHAR (a.auditdate,'yyyy')
order by
c.name,
TO_CHAR (a.auditdate,'yyyy');
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------
Plan hash value: 3362169395
---------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 27193 | 1513K| | 145K (1)| 00:29:03 |
| 1 | SORT GROUP BY | | 27193 | 1513K| 1824K| 145K (1)| 00:29:03 |
|* 2 | TABLE ACCESS BY INDEX ROWID | DAUDITNEW | 216 | 4968 | | 1149 (0)| 00:00:14 |
| 3 | NESTED LOOPS | | 27193 | 1513K| | 144K (1)| 00:28:59 |
| 4 | NESTED LOOPS | | 126 | 4284 | | 6 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| KUAF | 1 | 24 | | 1 (0)| 00:00:01 |
|* 6 | INDEX UNIQUE SCAN | KUAF_PRIMARY | 1 | | | 1 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID| KUAF | 126 | 1260 | | 5 (0)| 00:00:01 |
|* 8 | INDEX RANGE SCAN | KUAF_GROUPID | 126 | | | 1 (0)| 00:00:01 |
|* 9 | INDEX RANGE SCAN | DAUDITNEW_INDEXUSER | 86701 | | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("A"."AUDITSTR"='Login' AND TO_CHAR(INTERNAL_FUNCTION("A"."AUDITDATE"),'yyyy')>=:V_STARTDATE)
6 - access("C"."ID"=TO_NUMBER(:V_GROUPID))
8 - access("B"."GROUPID"=TO_NUMBER(:V_GROUPID))
9 - access("A"."PERFORMERID"="B"."ID")
log in
flush shared pool
initialize variables
execute sql
12:09:30 SQL> select
12:09:30 2 c.name group_name,
12:09:30 3 TO_CHAR (a.auditdate,'yyyy') yeartodate,
12:09:30 4 COUNT (a.auditdate) livelinklogins,
12:09:30 5 COUNT (DISTINCT a.performerid) distinctusers
12:09:30 6 from
12:09:30 7 dauditnew a,
12:09:30 8 kuaf b,
12:09:30 9 kuaf c
12:09:30 10 where
12:09:30 11 a.auditstr = 'Login'
12:09:30 12 and
12:09:30 13 TO_CHAR (a.auditdate,'yyyy') >= :v_startdate
12:09:30 14 and
12:09:30 15 a.performerid = b.id
12:09:30 16 and
12:09:30 17 b.groupid = :v_groupid
12:09:30 18 and
12:09:30 19 b.groupid = c.id
12:09:30 20 group by
12:09:30 21 c.name,
12:09:30 22 TO_CHAR (a.auditdate,'yyyy')
12:09:30 23 order by
12:09:30 24 c.name,
12:09:30 25 TO_CHAR (a.auditdate,'yyyy');
Group Year LiveLink Connects DISTINCTUSERS
------------ ---------------- ------------------- -------------
Admin_GPSW 2005 56,374 395
2006 142,974 518
2007 150,081 592
2008 166,149 848
2009 131,410 926
2010 120,271 944
************ -------------------
sum 767,259
6 rows selected.
12:16:29 SQL>
SQL Scripts
John, June 10, 2011 - 3:05 pm UTC
select client_id, term_eff_from_date, term_eff_to_date
from customers
where client_id in (1, 2, 3)
I need to create SQL Statement based effective from date and effective to date per client. I have active client and I need to calculate number of years with my company
1 Client ID - John Smith
08/22/2005 - 08/22/2011
06/30/2005 - 07/14/2005
04/15/2005 - 04/15/2006
I need to find out number of years client with our company.
Results should be 2320 / 365 = 6.356164 years
2 ClientID: Jenny
03/01/1993 - 06/30/1999
06/30/1999 - 07/30/2001
09/01/2003 - 09/01/2007
11/20/2007 - 06/30/2011
I need to find out number of years client with our company.
Results should be: 5852 / 365 = 16.03288 years
Client 3:
Example
6/1/1982 - 03/20/1996
4/1/1972 - 02/20/1996
Then need convert
06/01/1982 - 03/20/1996
04/01/1972 - 06/01/1982 -> see date cancellation date
Results 8754 / 365 days = 23.98356
Thanks
June 10, 2011 - 3:27 pm UTC
no create
no inserts
no look
string to date convertion
hitin, June 16, 2011 - 7:27 am UTC
Hi Tom
Would really appreciate if you could give some suggestions please.
I need to convert string to DATE in oracle.
I am getting values in the following formats all under one column-
5/31/2009 06:48 AM
6/1/2009 06:48:15 PM
etc.
So I cannot change the TO_DATE query as the column size is exceeding million records.
SELECT to_date('5/31/2009 06:48:09 AM','MM/DD/YYYY HH:MI:SS AM') FROM dual;
above query runs correctly, whereas lower one throws error.
SELECT to_date('5/31/2009 06:48 AM','MM/DD/YYYY HH:MI:SS AM') FROM dual;
-- it happens when there are 0 seconds so it just stores HH:MI and not HH:MI:SS
how can I convert using single TO_DATE command for all the columns?
your suggestions much appreciated.
Thanks,
Regards,
Hitin
June 17, 2011 - 1:38 pm UTC
So I cannot change the TO_DATE query as the column size is exceeding million
records.
that doesn't make sense to me, why can't you? You can do almost anything you want.
1,000,000 is such a small number these days too.
Tell us what the possible formats for this data are - all of them. If you cannot, then you cannot convert this data (that should be obvious). But tell us what all of the input formats will look like, and then we can tell you how to do it.
@hitin from india: string to date conversion
Stew Ashton, June 16, 2011 - 12:52 pm UTC
Hello Hitin,
It appears that Tom is busy elsewhere, so I dare propose this answer although you may not see it:
WITH DATA AS (
SELECT '5/31/2009 06:48 AM' INDATE FROM DUAL
UNION ALL
SELECT '6/1/2009 06:48:15 PM' INDATE FROM DUAL
)
SELECT TO_DATE(
INDATE,
CASE WHEN INDATE LIKE '%:%:%' THEN 'MM/DD/YYYY HH:MI:SS AM'
ELSE 'MM/DD/YYYY HH:MI AM' END
) outdate from data;
OUTDATE
-------------------
2009-05-31 06:48:00
2009-06-01 18:48:15
June 17, 2011 - 1:40 pm UTC
as long as the only two formats are that - yes, I was going to propose a case statement with like's to find the correct format when I got the list myself :)
Date difference
Reader, June 20, 2011 - 9:53 am UTC
Hi Tom,
I need to report the difference between two dates by excluding weekend dates ( i.e. Saturday & Sunday ). Consider the following:
create table date_tbl
(date1 date,
date2 date);
insert into date_tbl values(to_date('16-JUN-2011 13:00','DD-MON-RRRR HH24:MI'),sysdate);
insert into date_tbl values(to_date('17-JUN-2011 17:10','DD-MON-RRRR HH24:MI'),sysdate);
insert into date_tbl values(to_date('19-JUN-2011 10:13','DD-MON-RRRR HH24:MI'),sysdate);
insert into date_tbl values(to_date('18-JUN-2011 14:30','DD-MON-RRRR HH24:MI'),sysdate);
COMMIT;
select to_char(date1,'DD-MON-RRRR HH24:MI') date1,
to_char(date2,'DD-MON-RRRR HH24:MI') date2
from date_tbl;
So for the above,
(1) when calculating the difference between 16th & 20th of June 2011, I need to exclude 18th & 19th of June 2011.
(2) when calculating the difference between 17th & 20th of June 2011, I need to exclude 18th & 19th of June 2011.
(3) when calculating the difference between 18th & 20th of June 2011, I need to exclude 18th & 19th of June 2011.
(4) when calculating the difference between 19th & 20th of June 2011, I need to exclude 19th of June 2011.
Can a query be written to achive this. Please advise.
Many Thanks
Thank You Stew Ashton
hitin, June 21, 2011 - 5:22 am UTC
Your suggestion was very helpful....
Please Help In Following
Monty, October 05, 2011 - 8:00 am UTC
Hi Tom,
I need to get daily records between sysdate 00:00:00 to current sysdate like wise everyday i need to get these records so can you suggest me proper query for this
Thanks in advance..
i tried following
select * from tablename where TestTime between to_date(to_char(trunc(sysdate)||' 00:00:00'),'DD/MM/RRRR HH24:MI:SS') and to_date(to_char(trunc(sysdate)||' 23:59:59'),'DD/MM/RRRR HH24:MI:SS')
October 05, 2011 - 10:57 am UTC
select *
from t
where dt >= trunc(sysdate,'dd')
and dt < trunc(sysdate+1,'dd')
try to avoid ever using to_char/to_date to perform date stuff, use trunc, add_montths and math (addition) to do that.
How can I write this better using Math or Trunc?
Marco, October 29, 2012 - 2:11 pm UTC
Tom,
Following up on what you said "using math or trunc" how can I turn the following using math or trunc.
AND (((X.STUDENT_TS > TO_TIMESTAMP('2012/09/13 15:17:03.000000','YYYY/MM/DD HH24:MI:SS.FF'))
AND (X.STUDENT_TS <= TO_TIMESTAMP(TO_CHAR(TRUNC(SYSDATE) +17/23,'MM/DD/YYYY HH24:MI:SS'),'MM/DD/YYYY HH24:MI:SS.FF')))
OR
((P.STUDENT_TS > TO_TIMESTAMP('2012/09/13 17:05:12.376629','YYYY/MM/DD HH24:MI:SS.FF'))
AND (P.STUDENT_TS <= TO_TIMESTAMP(TO_CHAR(TRUNC(SYSDATE) +17/23,'MM/DD/YYYY HH24:MI:SS'),'MM/DD/YYYY HH24:MI:SS.FF'))))
October 29, 2012 - 9:05 pm UTC
how about you tell us what you are trying to do.
but it looks like you've already done it correctly.
where database_column > ? and database_column <= ?
that is good. you are not using a function on the database column unnecessarily
Thanks for Looking at it.
marco, October 30, 2012 - 3:06 pm UTC
Tom,
Thanks for looking at my code. I thought I was doing something wrong or it could have been written a bit better since you said "try to avoid ever using to_char/to_date to perform date stuff, use trunc, add_montths and math addition) to do that". I noticed that the Date range takes a lot longer than the
actual select/outer joined.
SELECT
A.STUDENT_ID,
A.BUDGET,
A.UNIVERSITY,
B.sUBSTEACHER,
A.PRINCIPAL,
A.DISTRICT,
B.SBR_ID,
B.univ_SEQ_NO
FROM
student A FULL OUTER JOIN student_region B
ON A.student_ID=B.student_id
AND A.region_NO=B.region_NO
AND A.univ_SEQ_NO=B.univ_SEQ_NO
A.REQUEST_STATUS_CODE IN ('LA', 'NY', 'NJ', 'DE', 'FL)
AND (((X.STUDENT_TS > TO_TIMESTAMP('2012/09/13 15:17:03.000000','YYYY/MM/DD HH24:MI:SS.FF'))
AND (X.STUDENT_TS <= TO_TIMESTAMP(TO_CHAR(TRUNC(SYSDATE) +17/23,'MM/DD/YYYY
HH24:MI:SS'),'MM/DD/YYYY HH24:MI:SS.FF')))
OR
((P.STUDENT_TS > TO_TIMESTAMP('2012/09/13 17:05:12.376629','YYYY/MM/DD HH24:MI:SS.FF'))
AND (P.STUDENT_TS <= TO_TIMESTAMP(TO_CHAR(TRUNC(SYSDATE) +17/23,'MM/DD/YYYY
HH24:MI:SS'),'MM/DD/YYYY HH24:MI:SS.FF'))))
AND EXISTS (SELECT 1 FROM SCHOOL_DISTRICT
WHERE SCHOOL_DISTRICT.STUD_ID=A.STUD_ID)
select SYSDATE from any_table;
Al Ricafort, November 01, 2012 - 9:12 pm UTC
Dear Tom,
Why is the output SYSDATE does not change per record if I issue below SQL?
All along I thought that SYSDATE is like a function call so would behave much like if you issue a sql like 'SELECT DBMS_RANDOM.RANDOM FROM ALL_TABLES'.
SQL>SELECT SYSDATE from ALL_TABLES;
:
:
SYSDATE
--------------------------
02-nov-2012 09:54:50
02-nov-2012 09:54:50
02-nov-2012 09:54:50
02-nov-2012 09:54:50
02-nov-2012 09:54:50
02-nov-2012 09:54:50
02-nov-2012 09:54:50
02-nov-2012 09:54:50
3588 rows selected.
November 01, 2012 - 10:31 pm UTC
sysdate is statement level deterministic by design, it would be *useless* otherwise in SQL (think about it)
select * from big_table where created between trunc(sysdate) and trunc(sysdate)+1-1/24/60;
if sysdate was changing - that query would return some really strange results wouldn't it. If you ran that query right before midnight, you'd get some records from today - and some from 'tomorrow' when the clock advances past midnight. You would never be able to use sysdate if it wasn't this way.
SELECT DBMS_RANDOM.RANDOM FROM ALL_TABLES
Sokrates, November 02, 2012 - 3:09 am UTC
@Al Ricafort,
what does
SELECT DBMS_RANDOM.RANDOM FROM ALL_TABLES
return for you ?
I assume, a series of different pseudo-random numbers ?
( So it does in my Oracle Version at the moment. )
Please note, that the implementation of your SQL-engine is free to behave differently: it could return the same first chosen pseudo-random numbers all again ( it is free to behave for example in a "statement level deterministic" manner here also ).
See
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:3181424400346795479 for an interesting discussion on a similar topic
SELECT DBMS_RANDOM.RANDOM FROM ALL_TABLES
Al Ricafort, November 04, 2012 - 8:37 pm UTC
@Sokrates
Thanks for the link. Very interesting discussion indeed.
Sangeetha P, February 01, 2013 - 11:14 am UTC
Hi Tom,
I faced an issue with date format. I was trying to do
date formatting as below as I need to fetch data from a table in which data is stored against each week of day.
1 , 2 etc where 1 is MON , 2 is TUE etc.
In SQL developer when I run this query it returns me 7.
SELECT TO_CHAR(to_date('27/01/2013','dd/mm/rrrr'), 'D') FROM dual
So as an output of my program I was expecting the value against 7. When I executed the procedure from SQL Developer it gives the result correctly. but when the procedure is called form .NET it returned me data against day '1'. I am not sure whether I am missing anything in the logic, or whether someone else also faced this issue.
Now I changed my code like this
CASE
WHEN TO_CHAR(DATE_TAB.LOOP_DATE, 'D') =1
THEN 7
ELSE TO_CHAR(DATE_TAB.LOOP_DATE, 'D') -1
END and everything working OK.
I am confused. Whether this is a bug or am I doing something wrong.
Thanks and Regards
Sangeetha
February 01, 2013 - 3:19 pm UTC
you have different NLS settings when you run sqldeveloper than you did when you used .net.
specifically, the nls_territory must be different (it'll default from your NLS_LANG which is probably what is really different)
http://docs.oracle.com/cd/B12037_01/server.101/b10749/ch3globe.htm#1006576 ops$tkyte%ORA11GR2> SELECT TO_CHAR(to_date('27/01/2013','dd/mm/rrrr'), 'D' ) FROM dual;
T
-
1
ops$tkyte%ORA11GR2> alter session set nls_territory = germany;
Session altered.
ops$tkyte%ORA11GR2> SELECT TO_CHAR(to_date('27/01/2013','dd/mm/rrrr'), 'D' ) FROM dual;
T
-
7
different places in the world consider different days to be the first day of the week.
that said... we can use IW (ISO standard- worldwide) with trunc and a bit of math to do this:
ops$tkyte%ORA11GR2> alter session set nls_territory = america;
Session altered.
ops$tkyte%ORA11GR2> select dt, to_char(dt,'dy'), trunc(dt)-trunc(dt, 'IW')+1
2 from ( SELECT to_date('27/01/2013','dd/mm/rrrr')+level-1 dt from dual connect by level <= 7);
DT TO_ TRUNC(DT)-TRUNC(DT,'IW')+1
--------- --- --------------------------
27-JAN-13 sun 7
28-JAN-13 mon 1
29-JAN-13 tue 2
30-JAN-13 wed 3
31-JAN-13 thu 4
01-FEB-13 fri 5
02-FEB-13 sat 6
7 rows selected.
ops$tkyte%ORA11GR2> alter session set nls_territory = germany;
Session altered.
ops$tkyte%ORA11GR2> select dt, to_char(dt,'dy'), trunc(dt)-trunc(dt, 'IW')+1
2 from ( SELECT to_date('27/01/2013','dd/mm/rrrr')+level-1 dt from dual connect by level <= 7);
DT TO_ TRUNC(DT)-TRUNC(DT,'IW')+1
-------- --- --------------------------
27.01.13 sun 7
28.01.13 mon 1
29.01.13 tue 2
30.01.13 wed 3
31.01.13 thu 4
01.02.13 fri 5
02.02.13 sat 6
7 rows selected.
Sangeetha P, February 02, 2013 - 10:52 pm UTC
Oh OK. Thank you so much. In .NET when we executed weekday() function it was returning 0 for Sunday.
Anyways will try with this .
Thanks again
Have a great day ahead..
Regards
Sangeetha
February 04, 2013 - 9:44 am UTC
and if you look at weekday()
http://tinyurl.com/d7l3d3f you can see they default the first day of the week to sunday in all locations - but allow you to override it with an optional second parameter. we rely on NLS settings for an application to ascertain the correct default.
beware of first days of weeks - in all API's - they should all be location dependent (or they are wrong ;) )
Sangeetha P, February 18, 2013 - 11:42 pm UTC
Thank you so much for the inputs Tom.
Regards
Sangeetha
No Date being returned
Bob, September 06, 2013 - 11:14 am UTC
I have a partitioned table "x", partitioned by x_id and a record in it as follows:
my_dt is defined as a date.
select my_dt dt, to_char(my_dt, 'DD-MON-YYYY HH24:MI:SS' ) dt_fully_formatted from x where x_id = 'C_8504'
Output is as follows:
dt = 31/03/2013
dt_fully_formatted = 31-MAR-2013 00:00:00
I ran he folowing piece of code to set the nls_date_format:
alter session set nls_date_format = 'DD-MON-YYYY'
Now, if I do the following:
select my_dt dt, to_char(my_dt, 'DD-MON-YYYY HH24:MI:SS' ) dt_fully_formatted from x where x_id = 'C_8504' and my_dt = '31-MAR-2013'
I get zero records returned. Any ideas why?
September 10, 2013 - 9:24 am UTC
never ever rely on implicit conversions, not in C, not in Java, not in SQL, not in PLSQL. bad things always happen.
you don't really give me much to go on here, no creates, no inserts.
this is what I would do to start debugging this.
ops$tkyte%ORA11GR2> CREATE TABLE t
2 (
3 my_dt date,
4 x_id varchar2(6),
5 y varchar2(30)
6 )
7 partition by hash(x_id)partitions 8
8 /
Table created.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> insert into t (my_dt,x_id,y) values ( to_date( '31-mar-2013' ), 'C_8504', 'hello world' );
1 row created.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> @bigdate
ops$tkyte%ORA11GR2> alter session set nls_date_format = 'dd-mon-yyyy hh24:mi:ss';
Session altered.
ops$tkyte%ORA11GR2> select dump(my_dt,16), my_dt from t where x_id = 'C_8504';
DUMP(MY_DT,16)
-------------------------------------------------------------------------------
MY_DT
--------------------
Typ=12 Len=7: 78,71,3,1f,1,1,1
31-mar-2013 00:00:00
ops$tkyte%ORA11GR2> create table tmp as select to_date( '31-mar-2013', 'dd-mon-yyyy' ) d from dual;
Table created.
ops$tkyte%ORA11GR2> select dump(d,16) from tmp;
DUMP(D,16)
-------------------------------------------------------------------------------
Typ=12 Len=7: 78,71,3,1f,1,1,1
You'll want to verify that the "dump" output is identical (use dump against a database column - do not dump( to_date( ... ) ) - that won't work right.)
if they do not match, then you might have a corrupt date in your table - that can easily be introduced by an application trying to be too "cute" (they bind a native 7 byte date and we accept whatever they give us, I've seen it all too often in many C programs...)
DB WORM
Parag PATANKAR, September 16, 2013 - 6:46 am UTC
Hi Tom,
I do not know, where this is a right place to ask this question. But it is quite urgent so I am asking this question, as you have blocked new question link.
I want to build WORM DB ( Write Once and Read Many ) in 12c. Nobody even DBA should be able to delete any DB transaction. This is my legal requirements. Is it possible to do so ? If yes can you elaborate in details ?
thanks and regards
PJP
September 24, 2013 - 4:50 pm UTC
your choices currently include:
a) you use discrentionary access control (grant) to permit only INSERT and SELECT.
b) you enable auditing for all users, including sys
in the event of an audit event - you would know immediately that a change has been made and you have access to flashback database, flashback table, point in time recovery to recover it
or, using flashback data archive, you maintain a secure history of all data at the row level. in the event of an audit event - you would be able to see the history of changes and see the original data
there isn't an "insert only" construct out of the box.
When you use Date Formats
nd, October 11, 2013 - 7:15 pm UTC
I was poking around my DB and trying to find a performance difference between these 2 date formats when querying large datasets. All my partitions and indexs are on timestamp format.
is there any reason not to use option 1 or over option 2?
1) ORDER_DATE BETWEEN '2012-05-03 00:00:00' AND '2012-05-04 00:00:00'
2) ORDER_DATE BETWEEN to_date('20120503','yyyymmdd') and to_date('20120504','yyyymmdd')
thanks!
November 01, 2013 - 6:04 pm UTC
you would want to use a date literal:
http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements003.htm#SQLRF51062 like "DATE '1998-12-25'"
scott%ORA11GR2> create table t
2 as
3 select to_date( '3-may-2012 12:00:00', 'dd-mon-yyyy hh24:mi:ss' ) dt
4 from dual;
Table created.
scott%ORA11GR2>
scott%ORA11GR2> alter session set nls_date_format = '...... hh24:mi:ss';
Session altered.
scott%ORA11GR2>
scott%ORA11GR2> select *
2 from t
3 where dt BETWEEN '2012-05-03 00:00:00' AND '2012-05-04 00:00:00'
4 /
DT
-------------------
2012-05-03 12:00:00
scott%ORA11GR2>
scott%ORA11GR2> alter session set nls_date_format = '..... hh24:mi:ss';
Session altered.
scott%ORA11GR2> select *
2 from t
3 where dt BETWEEN '2012-05-03 00:00:00' AND '2012-05-04 00:00:00'
4 /
no rows selected
you are relying on an NLS setting to be in place. if that assumption doesn't hold true - you lose.
NEVER rely on defaults.
always use a format with strings that contain dates.
or use a DATE LITERAL which has a fixed format that cannot be changed.
Date format conversions
Bala, March 10, 2014 - 9:08 am UTC
fnd_request.submit_request
(application => 'FND'
,program => 'FNDLGPRG'
,start_time => to_char(sysdate,'DD-MON-YYYY') || ' 20:00:00'
,argument1 => to_char(sysdate-4,'YYYY-MON-DD HH24:MI:SS')
,argument2 => chr(0)
);
I'm trying to schedule a concurrent request from backend directly to automate the process but start_time and argumen1 above are taking different date format because of that only its not getting scheduled i think. Its get executed only for the first time after it is scheduled but for subsequent runs argument1 value is taken as null, not sure why . Can you please help me in this case.
DataBase
Sevim, December 09, 2014 - 5:42 am UTC
I got a question that i need help with can someone tell be the answer for it please
Apparently the date or time data types come with a default string. Why do you think is so
December 09, 2014 - 4:28 pm UTC
they do not.
dates are 7 bytes of binary information
timestamps are 7 to 11 bytes of binary information
when a program, such as sqlplus, selects them - they typically bind them to a string host variable. We will implicitly convert the bytes into a friendly string using an NLS setting - such as the NLS_DATE_FORMAT which defaults to DD-MON-RR:
ops$tkyte%ORA11GR2> select sysdate from dual;
SYSDATE
---------
09-DEC-14
ops$tkyte%ORA11GR2> @bigdate
ops$tkyte%ORA11GR2> alter session set nls_date_format = 'dd-mon-yyyy hh24:mi:ss';
Session altered.
ops$tkyte%ORA11GR2> select sysdate from dual;
SYSDATE
--------------------
09-dec-2014 11:25:40
but you can change that default as I showed
better yet is to EXPLICTLY convert:
ops$tkyte%ORA11GR2> select to_char(sysdate, 'fmDay Month YYYY' ) from dual;
TO_CHAR(SYSDATE,'FMDAYMO
------------------------
Tuesday December 2014
That way you know what you are getting!
by the way, if you select date into a java date type for example, it'll be in java's internal way to represent a date - it isn't a 'string'. it is only when a program fetches the data into a host variable that is a string that this implicit conversion will happen!!!
dates are not strings are not dates
dates are not stored with a default string
a date is converted into a string using the NLS_DATE_FORMAT which can be specified in the to_char call, at the session level or defaulted in the databases init.ora
Days360
Harsh shah, November 12, 2019 - 7:27 am UTC
but I need to catch the 30 days of every month.
all months days are 30. now, this will be possible in oracle and kindly give me function for find days 360.
November 12, 2019 - 11:53 am UTC
all months days are 30
Nope! February has 29 at most!
What exactly are you trying to do?
Post a new question with full details of the problem.
ii
57, April 21, 2020 - 4:23 pm UTC
69
How do I offset time zone
Adi, August 07, 2020 - 9:52 pm UTC
So I use between to_date('2020/06/01','yyyy/mm/dd hh24:mi:ss' ) and To_date('2020/06/05','yyyy/mm/dd hh24:mi:ss') as a qualifier. However, the results don't reflect the time zone. In the select, I account for the time zone using this: To_char(cast((From_TZ(cast(p.BIRTH_DT_TM as TIMESTAMP),'+00:00') at time zone 'US/Mountain') as Date), 'YYYY-MM-DD') as DateOfBirth. Any thoughts?
August 10, 2020 - 2:12 am UTC
"It depends"
I mean - what assumptions are you making here? They were born in the same place as the server? etc etc...
Not entirely sure what you are asking here
I was 4 in 2000 fyi
A reader, February 08, 2021 - 4:21 pm UTC