J'ai un problème lorsque j'essaie de sélectionner des données dans une table filtrée par date.
Par exemple:
SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = '23/04/49';
L'erreur Oracle est:
Informe de error: Error SQL: ORA-01843: mes no válido 01843. 00000 - "not a valid month" *Cause: *Action:
Les données source de la table sont probablement corrompues, dans ce cas:
Les résultats de cette sélection, select * from nls_session_parameters;
, est:
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
Vous devriez utiliser le to_date
fonction ( Oracle/functions/to_date.php )
SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = TO_DATE('23/04/49', 'DD/MM/YY');
Vous comparez une colonne de date à un littéral de chaîne. Dans ce cas, Oracle tente de convertir votre littéral en une date, en utilisant le format de date par défaut. Il est déconseillé de s’appuyer sur un tel comportement, car cette valeur par défaut peut changer si le DBA modifie une configuration, Oracle rompt quelque chose dans une future révision, etc.
Au lieu de cela, vous devriez toujours explicitement convertir votre littéral en une date et indiquer le format que vous utilisez:
SELECT * FROM MYTABLE WHERE MYTABLE.DATEIN = TO_DATE('23/04/49','MM/DD/YY');
Si vous n'avez pas besoin de vérifier l'horodatage exact, utilisez
SELECT * FROM MYTABLE WHERE trunc(DATEIN) = TO_DATE('23-04-49','DD-MM-YY');
sinon, vous pouvez utiliser
SELECT * FROM MYTABLE WHERE DATEIN = TO_DATE('23-04-49 20:18:07','DD-MM-YY HH24:MI:SS');
Ici, vous utilisez la date du code, si vous comparez directement, vous devez utiliser JJ-MM-AA HH24: MI: SS sinon vous pourriez obtenir ORA-01849: heure doit être comprise entre 1 et 12.
Je sais que c'est un peu tard, mais j'ai un problème similaire. SQL*Plus
exécute la requête mais Oracle SQL Developer
montre le ORA-01843: not a valid month error.
SQL*Plus
semble savoir que la date que j’utilise est au format valide, alors qu’Oracle SQL Developer doit indiquer explicitement le format dans lequel se trouve ma date.
SQL*Plus statement
:
select count(*) from some_table where DATE_TIME_CREATED < '09-12-23';
CONTRE
Oracle SQL Developer statement
:
select count(*) from some_table where DATE_TIME_CREATED < TO_DATE('09-12-23','RR-MM-DD');
Juste au cas où cela aiderait, j'ai résolu le problème en vérifiant le format de date du serveur:
SELECT * FROM nls_session_parameters WHERE parameter = 'NLS_DATE_FORMAT';
puis en utilisant la comparaison suivante (le champ de gauche est une date + heure):
AND EV_DTTM >= ('01-DEC-16')
J'essayais cela avec TO_DATE
mais j'ai continué à avoir une erreur. Mais quand j'ai fait correspondre ma chaîne avec le NLS_DATE_FORMAT
et enlevé TO_DATE
, ça a marché...
Si la date source contient des minutes et des secondes, la comparaison des dates échouera. vous devez également convertir la date source au format requis en utilisant to_char et la date cible.
Dans un commentaire sur l'une des réponses, vous indiquez que la date avec un format n'aide pas. Dans un autre commentaire, vous expliquez que la table est accessible via DBLINK.
Il est donc évident que l'autre système contient une date non valide qu'Oracle ne peut accepter. Corrigez cela dans les autres dbms (ou ce que vous voulez faire disparaître) et votre requête fonctionnera.
Cela dit, je suis d’accord avec les autres: utilisez toujours to_date avec un format pour convertir un littéral de chaîne en date. Aussi, n'utilisez jamais que deux chiffres pendant un an. Par exemple, '23/04/49 'signifie 2049 dans votre système (format RR), mais cela déroute le lecteur (comme le montrent les réponses suggérant un format avec YY).