I have a problem when try to select data from a table filtering by date.
For example:
SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = '23/04/49';
The Oracle Error is:
Informe de error: Error SQL: ORA-01843: mes no válido 01843. 00000 - "not a valid month" *Cause: *Action:
Probably the source data of table is corrupted, in this case:
- How can i solve this problem?
- Can I change this dates for null?
The results of this select, select * from nls_session_parameters;
, is:
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_LANGUAGE SPANISH
NLS_TERRITORY SPAIN
NLS_CURRENCY ¿
NLS_ISO_CURRENCY SPAIN
NLS_NUMERIC_CHARACTERS ,.
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD/MM/RR
NLS_DATE_LANGUAGE SPANISH
NLS_SORT SPANISH
NLS_TIME_FORMAT HH24:MI:SSXFF
NLS_TIMESTAMP_FORMAT DD/MM/RR HH24:MI:SSXFF
NLS_TIME_TZ_FORMAT HH24:MI:SSXFF TZR
NLS_TIMESTAMP_TZ_FORMAT DD/MM/RR HH24:MI:SSXFF TZR
NLS_DUAL_CURRENCY ¿
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
asked Jan 16, 2014 at 8:56
2
You should use the to_date
function (oracle/functions/to_date.php
)
SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = TO_DATE('23/04/49', 'DD/MM/YY');
answered Jan 16, 2014 at 9:01
8
You are comparing a date column to a string literal. In such a case, Oracle attempts to convert your literal to a date, using the default date format.
It’s a bad practice to rely on such a behavior, as this default may change if the DBA changes some configuration, Oracle breaks something in a future revision, etc.
Instead, you should always explicitly convert your literal to a date and state the format you’re using:
SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = TO_DATE('23/04/49','MM/DD/YY');
answered Jan 16, 2014 at 9:03
MureinikMureinik
298k52 gold badges307 silver badges351 bronze badges
2
If you don’t need to check exact timestamp, use
SELECT * FROM MYTABLE WHERE trunc(DATEIN) = TO_DATE('23-04-49','DD-MM-YY');
otherwise, you can use
SELECT * FROM MYTABLE WHERE DATEIN = TO_DATE('23-04-49 20:18:07','DD-MM-YY HH24:MI:SS');
Here, you use hard code date,if you directly compare then you must use DD-MM-YY HH24:MI:SS else you might get ORA-01849: hour must be between 1 and 12.
answered Sep 14, 2017 at 6:43
I know this is a bit late, but I’m having a similar issue. SQL*Plus
executes the query successfully, but Oracle SQL Developer
shows the ORA-01843: not a valid month error.
SQL*Plus
seems to know that the date I’m using is in the valid format, whereas Oracle SQL Developer needs to be told explicitly what format my date is in.
-
SQL*Plus statement
:select count(*) from some_table where DATE_TIME_CREATED < '09-12-23';
VS
-
Oracle SQL Developer statement
:select count(*) from some_table where DATE_TIME_CREATED < TO_DATE('09-12-23','RR-MM-DD');
answered Aug 17, 2016 at 19:48
Just in case this helps, I solved this by checking the server date format:
SELECT * FROM nls_session_parameters WHERE parameter = 'NLS_DATE_FORMAT';
then by using the following comparison (the left field is a date+time):
AND EV_DTTM >= ('01-DEC-16')
I was trying this with TO_DATE
but kept getting an error. But when I matched my string with the NLS_DATE_FORMAT
and removed TO_DATE
, it worked…
zx485
28.5k28 gold badges50 silver badges59 bronze badges
answered Jan 4, 2017 at 22:51
In a comment to one of the answers you mention that to_date with a format doesn’t help. In another comment you explain that the table is accessed via DBLINK.
So obviously the other system contains an invalid date that Oracle cannot accept. Fix this in the other dbms (or whatever you dblink to) and your query will work.
Having said this, I agree with the others: always use to_date with a format to convert a string literal to a date. Also never use only two digits for a year. For example ’23/04/49′ means 2049 in your system (format RR), but it confuses the reader (as you see from the answers suggesting a format with YY).
answered Jan 16, 2014 at 11:13
Thorsten KettnerThorsten Kettner
89.6k7 gold badges49 silver badges73 bronze badges
3
If the source date contains minutes and seconds part, your date comparison will fail.
you need to convert source date to the required format using to_char and the target date also.
answered Jul 6, 2014 at 12:52
If you are using command line tools, then you can also set it in the shell.
On linux, with a sh type shell, you can do for example:
export NLS_TIMESTAMP_FORMAT='DD/MON/RR HH24:MI:SSXFF'
Then you can use the command line tools and it will use the specified format:
/path/to/dbhome_1/bin/sqlldr user/pass@host:port/service control=table.ctl direct=true
answered Aug 1, 2020 at 17:26
Try using:
SELECT *
FROM MYTABLE
WHERE MYTABLE.DATEIN is not null
AND MYTABLE.DATEIN = '23/04/49';
answered Mar 31, 2021 at 12:09
0
Use the month
as a string.
Example:
(12-Apr-2002) or (12-April-2002)
haydnD
2,2255 gold badges27 silver badges61 bronze badges
answered Mar 31, 2021 at 7:21
SaranSaran
211 bronze badge
0
Although the answers using TO_DATE are correct, I prefer to use the ANSI SQL format for dates:
DATEIN = DATE '1949-04-23'
It works in Oracle and other DBMS ANSI SQL compliant. This is specially important if your application is DBMS agnostic.
answered Aug 3, 2021 at 16:42
Lluis MartinezLluis Martinez
1,9638 gold badges28 silver badges42 bronze badges
Try alter session set NLS_DATE_FORMAT=’DD/MM/YY’; — or whatever format you want
I faced the same problem, on PROD, all the code were already in this format, but on preprod, it’s not set,
So this means you change the default date format used by oracle
answered Jan 9 at 8:12
ALTER session set NLS_LANGUAGE=’AMERICAN’;
answered Apr 13, 2020 at 17:33
2
I have a problem when try to select data from a table filtering by date.
For example:
SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = '23/04/49';
The Oracle Error is:
Informe de error: Error SQL: ORA-01843: mes no válido 01843. 00000 - "not a valid month" *Cause: *Action:
Probably the source data of table is corrupted, in this case:
- How can i solve this problem?
- Can I change this dates for null?
The results of this select, select * from nls_session_parameters;
, is:
PARAMETER VALUE
------------------------------ ----------------------------------------
NLS_LANGUAGE SPANISH
NLS_TERRITORY SPAIN
NLS_CURRENCY ¿
NLS_ISO_CURRENCY SPAIN
NLS_NUMERIC_CHARACTERS ,.
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD/MM/RR
NLS_DATE_LANGUAGE SPANISH
NLS_SORT SPANISH
NLS_TIME_FORMAT HH24:MI:SSXFF
NLS_TIMESTAMP_FORMAT DD/MM/RR HH24:MI:SSXFF
NLS_TIME_TZ_FORMAT HH24:MI:SSXFF TZR
NLS_TIMESTAMP_TZ_FORMAT DD/MM/RR HH24:MI:SSXFF TZR
NLS_DUAL_CURRENCY ¿
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
asked Jan 16, 2014 at 8:56
2
You should use the to_date
function (oracle/functions/to_date.php
)
SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = TO_DATE('23/04/49', 'DD/MM/YY');
answered Jan 16, 2014 at 9:01
8
You are comparing a date column to a string literal. In such a case, Oracle attempts to convert your literal to a date, using the default date format.
It’s a bad practice to rely on such a behavior, as this default may change if the DBA changes some configuration, Oracle breaks something in a future revision, etc.
Instead, you should always explicitly convert your literal to a date and state the format you’re using:
SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = TO_DATE('23/04/49','MM/DD/YY');
answered Jan 16, 2014 at 9:03
MureinikMureinik
298k52 gold badges307 silver badges351 bronze badges
2
If you don’t need to check exact timestamp, use
SELECT * FROM MYTABLE WHERE trunc(DATEIN) = TO_DATE('23-04-49','DD-MM-YY');
otherwise, you can use
SELECT * FROM MYTABLE WHERE DATEIN = TO_DATE('23-04-49 20:18:07','DD-MM-YY HH24:MI:SS');
Here, you use hard code date,if you directly compare then you must use DD-MM-YY HH24:MI:SS else you might get ORA-01849: hour must be between 1 and 12.
answered Sep 14, 2017 at 6:43
I know this is a bit late, but I’m having a similar issue. SQL*Plus
executes the query successfully, but Oracle SQL Developer
shows the ORA-01843: not a valid month error.
SQL*Plus
seems to know that the date I’m using is in the valid format, whereas Oracle SQL Developer needs to be told explicitly what format my date is in.
-
SQL*Plus statement
:select count(*) from some_table where DATE_TIME_CREATED < '09-12-23';
VS
-
Oracle SQL Developer statement
:select count(*) from some_table where DATE_TIME_CREATED < TO_DATE('09-12-23','RR-MM-DD');
answered Aug 17, 2016 at 19:48
Just in case this helps, I solved this by checking the server date format:
SELECT * FROM nls_session_parameters WHERE parameter = 'NLS_DATE_FORMAT';
then by using the following comparison (the left field is a date+time):
AND EV_DTTM >= ('01-DEC-16')
I was trying this with TO_DATE
but kept getting an error. But when I matched my string with the NLS_DATE_FORMAT
and removed TO_DATE
, it worked…
zx485
28.5k28 gold badges50 silver badges59 bronze badges
answered Jan 4, 2017 at 22:51
In a comment to one of the answers you mention that to_date with a format doesn’t help. In another comment you explain that the table is accessed via DBLINK.
So obviously the other system contains an invalid date that Oracle cannot accept. Fix this in the other dbms (or whatever you dblink to) and your query will work.
Having said this, I agree with the others: always use to_date with a format to convert a string literal to a date. Also never use only two digits for a year. For example ’23/04/49′ means 2049 in your system (format RR), but it confuses the reader (as you see from the answers suggesting a format with YY).
answered Jan 16, 2014 at 11:13
Thorsten KettnerThorsten Kettner
89.6k7 gold badges49 silver badges73 bronze badges
3
If the source date contains minutes and seconds part, your date comparison will fail.
you need to convert source date to the required format using to_char and the target date also.
answered Jul 6, 2014 at 12:52
If you are using command line tools, then you can also set it in the shell.
On linux, with a sh type shell, you can do for example:
export NLS_TIMESTAMP_FORMAT='DD/MON/RR HH24:MI:SSXFF'
Then you can use the command line tools and it will use the specified format:
/path/to/dbhome_1/bin/sqlldr user/pass@host:port/service control=table.ctl direct=true
answered Aug 1, 2020 at 17:26
Try using:
SELECT *
FROM MYTABLE
WHERE MYTABLE.DATEIN is not null
AND MYTABLE.DATEIN = '23/04/49';
answered Mar 31, 2021 at 12:09
0
Use the month
as a string.
Example:
(12-Apr-2002) or (12-April-2002)
haydnD
2,2255 gold badges27 silver badges61 bronze badges
answered Mar 31, 2021 at 7:21
SaranSaran
211 bronze badge
0
Although the answers using TO_DATE are correct, I prefer to use the ANSI SQL format for dates:
DATEIN = DATE '1949-04-23'
It works in Oracle and other DBMS ANSI SQL compliant. This is specially important if your application is DBMS agnostic.
answered Aug 3, 2021 at 16:42
Lluis MartinezLluis Martinez
1,9638 gold badges28 silver badges42 bronze badges
Try alter session set NLS_DATE_FORMAT=’DD/MM/YY’; — or whatever format you want
I faced the same problem, on PROD, all the code were already in this format, but on preprod, it’s not set,
So this means you change the default date format used by oracle
answered Jan 9 at 8:12
ALTER session set NLS_LANGUAGE=’AMERICAN’;
answered Apr 13, 2020 at 17:33
2
ORA-01843: not a valid month
ORA-01843 means that SQL engine cannot recognize the month value of your input string under current NLS_DATE_LANGUAGE. In this post, I will talk about some invalid month problems of ORA-01843 listed below:
- Misspelled Month Value
- Unmatched Month Value
- Foreign Month Value
- Compares Date with String
Misspelled Month Value
There might be typos in your statement just like the following example.
[oracle@test ~]$ export NLS_LANG=.UTF8
[oracle@test ~]$ sqlplus /nolog
...
SQL> conn hr/hr
Connected.
SQL> set heading off;
SQL> select value from v$nls_parameters where parameter = 'NLS_DATE_LANGUAGE';
AMERICAN
SQL> select TO_DATE('Augut 30, 2019', 'Month dd, YYYY') from dual;
select TO_DATE('Augut 30, 2019', 'Month dd, YYYY') from dual
*
ERROR at line 1:
ORA-01843: not a valid month
In the above TO_DATE example, we misspelled «August» as another one, that’s why SQL engine cannot recognize the month value. The solution is easy, please recheck your spelling and correct it to make it valid.
If you found nothing wrong, maybe you should paste your input string into a text editor and make it run spell checker. For example, the spell checker plugins of Notepad++.
SQL> select TO_DATE('August 30, 2019', 'Month dd, YYYY') from dual;
30-AUG-19
Unmatched Month Value
You might see there’s nothing wrong in your month value, but the month value you used may not be acceptable by Oracle. Let’s see an example.
First of all, switch NLS_DATE_LANGUAGE to JAPANESE.
SQL> alter session set nls_date_language='Japanese';
Session altered.
Then we used a term «八月» which also means «August» in Japanese.
SQL> select TO_DATE('八月 30, 2019', 'Month dd, YYYY') from dual;
select TO_DATE('八月 30, 2019', 'Month dd, YYYY') from dual
*
ERROR at line 1:
ORA-01843: not a valid month
Where to Find Valid Month Values?
Indeed, «八月» is also a correct expression of August in Japanese, but it’s invalid to Oracle. To solve such error pattern, you have to know valid and correct month values for different NLS_DATE_LANGUAGE. In this case, «八月» is invalid, «8月» is valid.
SQL> select TO_DATE('8月 30, 2019', 'Month dd, YYYY') from dual;
30-8月 -19
Foreign Month Value
For some reason, you might use a foreign month value in your statement like the following:
SQL> select TO_DATE('Août 30, 2019', 'Month dd, YYYY') from dual;
select TO_DATE('Août 30, 2019', 'Month dd, YYYY') from dual
*
ERROR at line 1:
ORA-01843: not a valid month
Under current NLS_DATE_LANGUAGE (Japanese), SQL engine doesn’t recognize «Août». You need to tell it how to translate it by adding NLS parameter option to make the month valid. But the next question is: what language should we use to translate it?
Where to Find Correct Language?
Again, for mapping what NLS_DATE_LANGUAGE should be used to translate the string, you should check valid month values for different languages. Consequently, «Août» is August in French.
SQL> select TO_DATE('Août 30, 2019', 'Month dd, YYYY', 'NLS_DATE_LANGUAGE=FRENCH') from dual;
30-8月 -19
Please note that, even though you used a very common English term «August» in the statement, it’s still not a valid month value under Japanese environment in case of ORA-01843.
SQL> select TO_DATE('August 30, 2019', 'Month dd, YYYY', 'NLS_DATE_LANGUAGE=AMERICAN') from dual;
30-8月 -19
Compares Date with String
In some cases, we saw users compare a datetime with a string like this:
SQL> select 'TRUE' "Compare" from dual where to_date('1/1/2010 23:20', 'MM/DD/YYYY HH24:MI:SS') < '01/01/2022 00:00:00';
select 'TRUE' from dual where to_date('1/1/2010 23:20', 'MM/DD/YYYY HH24:MI:SS') < '01/01/2022 00:00:00'
*
ERROR at line 1:
ORA-01843: not a valid month
In fact, a date value cannot compare with a string one, we should compare them on the same base.
SQL> select 'TRUE' "Compare" from dual where to_date('1/1/2010 23:20', 'MM/DD/YYYY HH24:MI:SS') < to_date('01/01/2022 00:00:00', 'MM/DD/YYYY HH24:MI:SS');
Comp
----
TRUE
As you can see, I use TO_DATE function on both operands to compare them on the same base.
To better know how to convert a string into date value, you may check: Oracle TO_DATE Function Examples.
Introduction
If you’re an Oracle SQL developer, you would have seen the «not a valid month» error quite a lot in your career. In this article, I’ll discuss what the error means and a few ways you can solve it.
Background
What Is The «Not a Valid Month» Error?
This error message appears in Oracle when you’re using the TO_DATE function in an SQL statement, but you get an error with the output:
ORA-01843: not a valid month
The TO_DATE function should be converting your input into a DATE value, but there is some error happening that’s preventing you from doing this.
TO_DATE Syntax
The syntax of the TO_DATE function is:
TO_DATE( string1, [ format_mask ], [nls_language ] )
The first parameter is your input string, and is the only mandatory field. The second parameter is the format mask of the input value, and the third is the language of the date value. We’ll cover both of these below.
Causes and Fixes for the Error
There are a few causes of this error.
First of all, the most common cause is how you’ve specified the month value inside your TO_DATE parameter.
It can often be a typo, such as entering a value of «13» for the month (as there are only 12 months) or entering a value of «JNA» instead of «JAN» for January.
SELECT TO_DATE('01-JNA-2015') FROM dual;
Fix: To fix this, update your SQL statement to remove the mistake and use the correct month value.
SELECT TO_DATE('01-JAN-2015') FROM dual;
If the value is correct, and you’re still getting the error, it could be to do with the format you’ve entered.
TO_DATE allows you to enter a format along with the input value. The format reflects what the input value is, not the output value, like some other functions. The output value is always a DATE, so it doesn’t need a format. The input value does need a format.
If you’ve entered a valid value for the month, such as «JAN» or 12, then it might be that your format does not match up to the input value.
For example:
SELECT TO_DATE('14-APR-2015', 'MM-DD-YYYY') FROM dual;
This query will show you an error because the value expected for the month is in the wrong order, and 14 is too high of a value for the month.
Fix: Either update the input value to match the format, or update the format to match the input value.
SELECT TO_DATE('14-APR-2015', 'DD-MON-YYYY') FROM dual;
Finally, if neither of those solutions work, or if you’re not specifying a format value, then it is most likely a database setting.
Sessions on your database are created in a certain language format or date format. These are set up when Oracle is installed, but can be modified for a session.
This is relevant because different locations and countries in the world have different ways of specifying dates.
You can find out what your database is doing by querying two values on your database.
The first is the NLS_DATE_LANGUAGE
SELECT * FROM nls_session_parameters WHERE parameter = 'NLS_DATE_LANGUAGE'; PARAMETER VALUE NLS_DATE_LANGUAGE ENGLISH
Your query should show something that is related to your location, such as ‘AMERICAN’. My example shows ‘ENGLISH’ as I’m based in Australia.
The second value, and probably the more important value for this error, is the NLS_DATE_FORMAT.
SELECT * FROM nls_session_parameters WHERE parameter = 'NLS_DATE_FORMAT'; PARAMETER VALUE NLS_DATE_FORMAT DD/MON/RR
This will show you the actual format that dates are expected to be in, if the format is not specified in the function.
As you can see, my format is ‘DD/MON/RR’. This is the format that the TO_DATE function expects. If the input I’m supplying is different to this, I’ll get an error.
SELECT TO_DATE('05-22-2015') FROM dual; ORA-01843: not a valid month
If you’re getting this error, it could be because your input value does not match the format for your database.
Fix: There are a couple of ways to fix this. Either change the input value in your function to match your format, specify a format inside your function.
You can also change the value of this database parameter for your session by using the ALTER SESSION command.
ALTER SESSION SET NLS_DATE_FORMAT = 'MM-DD-YYYY'; SELECT TO_DATE('05-22-2015') FROM dual; 05-22-2015
So, the «not a valid month» error can be resolved after looking into a few different causes. Most likely it’s a typing error or format mismatch, but there are a few ways to check.
History
Keep a running update of any changes or improvements you’ve made here.
Problem
Metric extract fails with error when using the _make_timestamp function in the time hierarchy mapping, even though the test sample produces valid looking date/time entries.
Symptom
PD-MD-0089 An error occurred in the execution of the metric values query for extract ‘<Extract Name>’.
RQP-DEF-0177 An error occurred while performing operation ‘sqlOpenResult’ status=’-28′.
UDA-SQL-0114 The cursor supplied to the operation «sqlOpenResult» is inactive.UDA-SQL-0107 A general exception has occurred during the operation
«open result».
ORA-01843: not a valid month
Cause
This error can occur if the column being used in the _make_timestamp function
is already a date/time column.
Environment
Oracle Metric Store
Resolving The Problem
Map the date/time column to the time hierarchy instead of using the _make_timestamp function.
Steps:
- From Cognos Metrics Designer, right-click the Metrics Extract referenced in the error and select Edit Definition.
- Click the Time Periods Mapping tab.
- Select the attribute with the _make_timestamp function and click Clear.
- From the Available Objects, drag the appropriate date/time column into the time period.
- Click OK.
[{«Product»:{«code»:»SSEP7J»,»label»:»Cognos Business Intelligence»},»Business Unit»:{«code»:»BU059″,»label»:»IBM Software w\/o TPS»},»Component»:»Metrics Designer»,»Platform»:[{«code»:»PF033″,»label»:»Windows»}],»Version»:»10.2.2;10.2.1;10.2″,»Edition»:»»,»Line of Business»:{«code»:»LOB10″,»label»:»Data and AI»}}]