Oracle is not working with Japanese OS issue - windows

I have a query which returns second and fourth saturdays of given year,
WITH ALL_SATURDAYS AS
(SELECT TO_CHAR(TO_DATE('01012014','DDMMYYYY'),'WW') * (level) AS WEEK_NO,
NEXT_DAY(TO_DATE('01012014','DDMMYYYY') + (TO_CHAR(TO_DATE('01012014','DDMMYYYY'),'WW' ) * (level-1) * 7),'土') AS SATURDAY_DATE,
row_number() OVER (PARTITION BY TO_CHAR(NEXT_DAY(TO_DATE('01012014','DDMMYYYY') + (TO_CHAR(TO_DATE('01012014','DDMMYYYY'),'WW' ) * (level-1) * 7),'土'),'月') ORDER BY level) AS Pos
FROM DUAL
CONNECT BY level<= 52
ORDER BY 1
)
SELECT SATURDAY_DATE,POS FROM ALL_SATURDAYS WHERE POS IN (2,4) ORDER BY 1,2
It's working in other systems, but mine is a japanese os when i execute this query it returns ORA-01821: date format not recognized error.
How can i fix the error?

Replace 月 with MONTH. The Datetime Format Elements are always in English, even though the results may be in another language.
alter session set nls_date_language=japanese;
select to_char(date '2014-01-01', 'MONTH') month from dual;
Month
-----
1月

Related

Generate range of dates using CTE Oracle

I want to generate a range of days between two different dates using recursive WITH clause in Oracle.
WITH CTE_Dates (cte_date) AS
( SELECT CAST(TO_DATE('10-02-2017', 'DD-MM-YYYY') AS DATE) cte_date FROM dual
UNION ALL
SELECT CAST( (cte_date + 1) AS DATE) cte_date
FROM CTE_Dates
WHERE TRUNC(cte_date) + 1 <= TO_DATE('20-02-2017', 'DD-MM-YYYY')
)
SELECT * FROM CTE_Dates
The returned results are completely other than expected:
10-02-2017
09-02-2017
08-02-2017
07-02-2017
06-02-2017
... (unlimited)
The expected results:
10-02-2017
11-02-2017
...
19-02-2017
20-02-2017
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production.
Edit:
As I understood, this is a known Bug in Oracle, the bug exists through Oracle 11.2.0.2 and it was fixed in 11.2.0.3.
Altarnative solution:
SELECT TRUNC (TO_DATE('10-02-2017', 'DD-MM-YYYY') + ROWNUM -1) dt
FROM DUAL
CONNECT BY ROWNUM <= (TO_DATE('20-02-2017', 'DD-MM-YYYY') - (TO_DATE('10-02-2017', 'DD-MM-YYYY')))
This was a known bug in recursive CTE's in Oracle 11 (specifically with regard to date arithmetic). Fixed in Oracle 12. Exactly that behavior: whether you add or subtract in your code, the engine always subtracts, it never adds.
EDIT: Actually, as Alex Poole pointed out in a Comment to the original post, the bug exists through Oracle 11.2.0.2 and it was fixed in 11.2.0.3. End edit
Alas I am not a paying customer, so I can't quote chapter and verse, but with a little bit of Googling you will find links to this (including on OTN where I was involved in a few threads discussing this and other bugs in recursive CTEs - some were fixed, some are still bugs in Oracle 12.1).
Added - here is one of those discussions: https://community.oracle.com/thread/3974408
Unless you really need to use the WITH clause there is another solution to get the expected result by using the CONNECT BY clause.
SELECT TO_DATE('10-02-2017', 'DD-MM-YYYY') AS date_range
FROM dual
UNION ALL
SELECT TO_DATE('10-02-2017', 'DD-MM-YYYY') + LEVEL
FROM dual
CONNECT BY LEVEL <= (TO_DATE('20-02-2017', 'DD-MM-YYYY') - TO_DATE('10-02-2017', 'DD-MM-YYYY'));
Maybe reverse order of the recursion solves the problem:
with cte_dates (cte_date) as (
select cast(to_date('20-02-2017', 'DD-MM-YYYY') as date) cte_date from dual
union all
select cast((cte_date - 1) as date) cte_date
from cte_dates
where cast(cte_date as date) > to_date('10-02-2017', 'DD-MM-YYYY')
)
select * from cte_dates
order by cte_date
;
2017-02-10
2017-02-11
2017-02-12
...
2017-02-18
2017-02-19
2017-02-20
Note: cast date as date needed due to yet another bug by RCTE in 11gR2
Old discussion here
You don't need a recursive WITH clause, you just need a table where number of rows > number of dates you want to generate :
WITH
dates
AS
(SELECT
TO_DATE('10-02-2017', 'DD-MM-YYYY') + (rownum - 1)
FROM
all_tables
WHERE 1=1
AND rownum < (TO_DATE('20-02-2017', 'DD-MM-YYYY') - TO_DATE('10-02-2017', 'DD-MM-YYYY')) + 2
)
SELECT
*
FROM
dates

generate date range per year basis

I want to generate date range between trunc('7/1/2014','mm/dd/yyyy') and trunc(sysdate-1)+0.99999 (from 7/1/2014 till yesterday midnight) per year basis.
please refer to the attached image for expected result (https://i.stack.imgur.com/UD4Ub.png)
Something like this. Adapt as needed. You probably won't select * from ranges but instead you will use the ranges wherever/however you need them. The input date dt, selected from a table input_date in my solution, may instead be a bind variable in your application, etc. Hope you are able to figure out the adjustments yourself; if not, please write back.
with
input_date ( dt ) as (
select to_date('07/01/2014', 'mm/dd/yyyy')
from dual
),
ranges ( date_from, date_to ) as (
select add_months(dt, 12 * (level - 1)) + level - 1,
least(trunc(sysdate), add_months(dt, 12 * level) + level - 1)
from input_date
connect by add_months(dt, 12 * (level - 1)) + level - 1 <= trunc(sysdate)
)
select * from ranges
;
DATE_FROM DATE_TO
---------- ----------
07/01/2014 07/01/2015
07/02/2015 07/02/2016
07/03/2016 11/28/2016

Get date of the previous day in Oracle

I need to bring the day immediately preceding date in Oracle using a truncate but not how. He was using the following line but bring me some records for the current day of execution and should not be. Neceisto only the previous day; investigation found the truncate with dates in Oracle but not how to use it.
and fnxs.FECHA_INGRESO BETWEEN (TO_CHAR (SYSDATE-1, 'DD-MON-YY')) AND (TO_CHAR (SYSDATE, 'DD-MON-YY'));
I appreciate your help
Using BETWEEN with dates in Oracle is generally a bad idea. I see it all the time, and most of the time people get it wrong (like in the accepted answer above). Even when they fully understand that the two dates are included, they still make logical errors because they forget about timestamps.
The OP is asking for yesterday dates. The following sql shows that today falls within "BETWEEN TRUNC( SYSDATE ) - 1 AND TRUNC( SYSDATE )"
with adate as (
select trunc(sysdate) today from dual
) select today from adate where today between trunc(sysdate) -1
and trunc(sysdate);
16-Apr-15 00:00:00
[returns the record for today]
I find it easier to be correct with dates when you're more explicit about the end points:
SELECT * from your_table
WHERE fnxs.FECHA_INGRESO >= TRUMC(SYSDATE) - 1
AND fnxs.FECHA_INGRESO < TRUNC(SYSDATE);
Upon looking closer, the OP's date-like column might be a VARCHAR2 (could still be a date that was implicitly cast in the comparison he gave). If it is a VARCHAR, then it needs to be converted first (using an appropriate format string):
SELECT * FROM your_table
WHERE TO_DATE(fnxs.FECHA_INGRESO, 'DD-MON-YY') >= TRUMC(SYSDATE) - 1
AND TO_DATE(fnxs.FECHA_INGRESO, 'DD-MON-YY') < TRUNC(SYSDATE);
Assuming your column is of type DATE
SELECT *
FROM TABLE_NAME
WHERE FECHA_INGRESO BETWEEN TRUNC( SYSDATE ) - 1
AND TRUNC( SYSDATE );
If it is a character string then:
SELECT *
FROM TABLE_NAME
WHERE TO_DATE( FECHA_INGRESO, 'DD-MON-YY' )
BETWEEN TRUNC( SYSDATE ) - 1
AND TRUNC( SYSDATE );

Using a case when to know if date format is right

I want to migrate a table which contains some columns with dates. The issue is my dates are often in dd/mm/yyyyy HH24:MM:YYYY format. But sometimes it appears that the format is only dd/mm/yyyy, or blank.
I guess that's why I'm getting ORA-01830 when I'm trying to migrate the datas.
I tried
CASE
WHEN TO_DATE(MYDATE,'DD/MM/YYYY')
then TO_DATE(MYDATE,'DD/MM/YYYY 00:00:00')
END AS MYDATE
But I'm not sure if it is possible to test the date format (and ofcourse it's not working).
Thank you
TO_DATE cannot test date format, but you can do it. If Lalit's answer would not be enough, try something like
select
case when my_date like '__/__/__' then to_date(my_date, 'dd/mm/yy')
when my_date like '__-__-__' then to_date(my_date, 'dd-mm-yy')
...
end
So you have the data type issue. DATE is stored as string literal. As you have mentioned that the date model has the DD/MM/YYYY part same, just that the time portion is either missing for some rows or the entire value is NULL.
For example, let's say your table have the values like -
SQL> WITH dates AS(
2 SELECT 1 num, '29/12/2014 16:38:57' dt FROM dual UNION ALL
3 SELECT 2, '29/12/2014' FROM dual UNION ALL
4 SELECT 3, NULL FROM dual
5 )
6 SELECT num, dt
7 FROM dates
8 /
NUM DT
---------- -------------------
1 29/12/2014 16:38:57
2 29/12/2014
3
SQL>
TO_DATE with proper format model should do the trick.
Let's stick to a format model first.
SQL> alter session set nls_date_format='dd/mm/yyyy hh24:mi:ss';
Session altered.
Now, let's use TO_DATE to explicitly convert the string literal to date.
SQL> WITH dates AS(
2 SELECT 1 num, '29/12/2014 16:38:57' dt FROM dual UNION ALL
3 SELECT 2, '29/12/2014' FROM dual UNION ALL
4 SELECT 3, NULL FROM dual
5 )
6 SELECT num, to_date(dt, 'dd/mm/yyyy hh24:mi:ss') dt
7 FROM dates
8 /
NUM DT
---------- -------------------
1 29/12/2014 16:38:57
2 29/12/2014 00:00:00
3
SQL>

Oracle Date - How to add years to date

I have a date field
DATE = 10/10/2010
sum = 4 (this are number of years by calculation)
is there a way to add four years to 10/10/2010 and make it
10/10/2014?
Try adding months (12 * number of years) instead. Like this-
add_months(date'2010-10-10', 48)
Use add_months
Example:
SELECT add_months( to_date('10-OCT-2010'), 48 ) FROM DUAL;
Warning
add_months, returns the last day of the resulting month if you input the last day of a month to begin with.
So add_months(to_date('28-feb-2011'),12) will return 29-feb-2012 as a result.
I believe you could use the ADD_MONTHS() function. 4 years is 48 months, so:
add_months(DATE,48)
Here is some information on using the function:
http://www.techonthenet.com/oracle/functions/add_months.php
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1157035034361
You can try this:
someDate + interval '4' year
INTERVAL
I am not sure, if I understood Your question correctly, but
select add_months(someDate, numberOfYears * 12) from dual
might do the trick
One more option apart from ADD_MONTHS
SELECT
SYSDATE,
SYSDATE
+ TO_YMINTERVAL ( '1-0' )
FROM
DUAL;
SYSDATE SYSDATE+TO_YMINTERVAL('1-0')
--------- ----------------------------
29-OCT-13 29-OCT-14
1 row selected.
SELECT
SYSDATE,
SYSDATE
+ TO_YMINTERVAL ( '2-0' )
FROM
DUAL;
SYSDATE SYSDATE+TO_YMINTERVAL('2-0')
--------- ----------------------------
29-OCT-13 29-OCT-15
1 row selected.
SELECT
TO_DATE ( '29-FEB-2004',
'DD-MON-YYYY' )
+ TO_YMINTERVAL ( '1-0' )
FROM
DUAL
*
Error at line 4
ORA-01839: date not valid for month specified
But the last one is illegal since there is no 29th day of February in 2005, hence it fails on leap year cases (Feb 29)
Read the documentation for the same
SELECT TO_CHAR(SYSDATE,'YYYY')-2 ANO FROM DUAL

Resources