Comparaison des dates dans Oracle SQL

141

J'essaie de le faire afficher le nombre d'employés embauchés après le 20 juin 1994, mais j'obtiens une erreur disant "JUN" identifiant invalide. Veuillez aider, merci!

Select employee_id, count(*)
From Employee
Where to_char(employee_date_hired, 'DD-MON-YY') > 31-DEC-95; 
user1336830
la source
1
Notez également que vous pouvez utiliser soit > <ouBETWEEN '' AND ''
Andrew

Réponses:

297

31-DEC-95n'est pas une chaîne, ni ne l'est 20-JUN-94. Ce sont des chiffres avec des éléments supplémentaires ajoutés à la fin. Cela devrait être '31-DEC-95'ou '20-JUN-94'- noter la citation unique '. Cela vous permettra de faire une comparaison de chaînes.

Cependant, vous ne faites pas de comparaison de chaînes; vous faites une comparaison de dates . Vous devez transformer votre chaîne en date. Soit en utilisant la TO_DATE()fonction intégrée, soit un littéral de date .

À CE JOUR()

select employee_id
  from employee
 where employee_date_hired > to_date('31-DEC-95','DD-MON-YY')

Cette méthode présente quelques pièges inutiles

  • Comme a_horse_with_no_name noté dans les commentaires DEC, ne signifie pas nécessairement décembre. Cela dépend de vos paramètres NLS_DATE_LANGUAGEet NLS_DATE_FORMAT. Pour vous assurer que votre comparaison fonctionne dans tous les paramètres régionaux, vous pouvez utiliser le modèle de format datetime à la MM place
  • L'année 95 est inexacte. Vous savez que vous voulez dire 1995, mais que se passerait-il si c'était 50, est-ce que c'est 1950 ou 2050? Il vaut toujours mieux être explicite
select employee_id
  from employee
 where employee_date_hired > to_date('31-12-1995','DD-MM-YYYY')

Littéraux de date

Un littéral de date fait partie de la norme ANSI, ce qui signifie que vous n'avez pas besoin d'utiliser une fonction spécifique à Oracle. Lorsque vous utilisez un littéral, vous devez spécifier votre date dans le format YYYY-MM-DDet vous ne pouvez pas inclure d'élément d'heure.

select employee_id
  from employee
 where employee_date_hired > date '1995-12-31'

N'oubliez pas que le type de données de date Oracle inclut un élément d'heure, de sorte que la date sans partie d'heure équivaut à 1995-12-31 00:00:00.

Si vous souhaitez inclure une partie de l'heure, vous devez utiliser un littéral d'horodatage, qui prend le format YYYY-MM-DD HH24:MI:SS[.FF0-9]

select employee_id
  from employee
 where employee_date_hired > timestamp '1995-12-31 12:31:02'

Informations complémentaires

NLS_DATE_LANGUAGEest dérivé NLS_LANGUAGEet NLS_DATE_FORMATdérivé de NLS_TERRITORY. Celles-ci sont définies lors de la création initiale de la base de données, mais elles peuvent être modifiées en modifiant votre fichier de paramètres d'inialisation - uniquement si cela est vraiment nécessaire - ou au niveau de la session en utilisant la ALTER SESSIONsyntaxe. Par exemple:

alter session set nls_date_format = 'DD.MM.YYYY HH24:MI:SS';

Ça signifie:

  • DD jour numérique du mois, 1 - 31
  • MM mois numérique de l'année, 01-12 (janvier est 01)
  • YYYYAnnée à 4 chiffres - à mon avis, c'est toujours mieux qu'une année à 2 chiffres YYcar il n'y a aucune confusion avec le siècle auquel vous faites référence.
  • HH24 heure de la journée, 0-23
  • MI minute de l'heure, 0 - 59
  • SS seconde de la minute, 0-59

Vous pouvez trouver votre langue actuelle et vos paramètres de langue de date en interrogeant V$NLS_PARAMETERSset la gamme complète des valeurs valides en interrogeant V$NLS_VALID_VALUES.

Lectures complémentaires


Incidemment, si vous voulez que count(*)vous ayez besoin de grouper paremployee_id

select employee_id, count(*)
  from employee
 where employee_date_hired > date '1995-12-31'
 group by employee_id

Cela vous donne le nombre par employee_id .

Ben
la source
13
+1 pour l'utilisation d'un masque de format dans to_date (). Notez que cela peut toujours échouer sur des environnements différents en raison de paramètres de langue différents. DECn'est pas nécessairement toujours un mois valide. Il est généralement préférable d'utiliser des nombres plutôt que des noms
a_horse_with_no_name
1
Vous pouvez spécifier une heure avec un littéral ANSI - il vous suffit de spécifier un timestamplittéral au lieu d'un datelittéral: timestamp '2015-01-30 19:42:04' (car dans ANSI SQL a le datetype de données n'a pas d'heure, seul le timestamptype de données en a).
a_horse_with_no_name
1
Les littéraux de date ANSI sont vraiment un moyen concis de comparer le fait de devoir taper TO_DATE et Date-Format à chaque fois. Bon pour les développeurs LAZY comme moi. Une chose à noter est vraiment les DATE 2016-04-01moyens 2016-04-01 00:00:00. Et je pense que cette syntaxe fonctionne depuis Oracle 9i car c'est là que la syntaxe ANSI-SQL a été introduite dans Oracle.
LeOn - Han Li
1
Ma réflexion a considérablement évolué au cours des 4 dernières années @Leon :-) «J'ai mis à jour la réponse. J'avais mentionné qu'un littéral de date n'incluait pas d'élément de temps, mais je l'ai appelé plus explicitement comme vous l'avez déclaré. Le support étendu de 9i a pris fin il y a presque 6 ans ... et est sorti il ​​y a 14 ans. Cela ne devrait plus être pertinent pour la grande majorité des utilisateurs.
Ben
6

Conclusion,

to_char fonctionne à sa manière

Alors,

Utilisez toujours ce format AAAA-MM-JJ pour la comparaison au lieu de MM-JJ-AA ou JJ-MM-AAAA ou tout autre format

akshay gulawane
la source
4

Vous pouvez utiliser trunc et to_date comme suit:

select TO_CHAR (g.FECHA, 'DD-MM-YYYY HH24:MI:SS') fecha_salida, g.NUMERO_GUIA, g.BOD_ORIGEN, g.TIPO_GUIA, dg.DOC_NUMERO, dg.* 
from ils_det_guia dg, ils_guia g
where dg.NUMERO_GUIA = g.NUMERO_GUIA and dg.TIPO_GUIA = g.TIPO_GUIA and dg.BOD_ORIGEN = g.BOD_ORIGEN
and dg.LAB_CODIGO = 56 
and trunc(g.FECHA) > to_date('01/02/15','DD/MM/YY')
order by g.FECHA;
Giovanny Farto M.
la source
2

à partir de votre requête:

Select employee_id, count(*) From Employee 
Where to_char(employee_date_hired, 'DD-MON-YY') > '31-DEC-95' 

Je pense que ce n'est pas pour afficher le nombre d'employés embauchés après le 20 juin 1994. si vous voulez afficher le nombre d'employés, vous pouvez utiliser:

Select count(*) From Employee 
Where to_char(employee_date_hired, 'YYYMMMDDD') > 19940620 

Je pense que pour comparer les dates, vous pouvez utiliser les meilleures pratiques:

employee_date_hired > TO_DATE('20-06-1994', 'DD-MM-YYYY');
or
to_char(employee_date_hired, 'YYYMMMDDD') > 19940620;
viduka
la source
-4

Le guillemet simple doit être présent, car la date est convertie en caractère.

Sélectionnez Employee_id, count (*)
De l'employé
Où to_char (date_employé_embauché, 'JJ-MON-AA')> '31 -DEC-95 ';
MVB
la source
1
Ce SQL utilise un format de date implicite, il ne fonctionnera pas toujours.
Jon Heller
5
Cela ne fonctionne que pour vos paramètres NLS_ * spécifiques, cela peut ne pas fonctionner sur d'autres clients ou serveurs. La réponse acceptée explique pourquoi un format de date explicite est important.
Jon Heller
Cette méthode compare des chaînes, pas des dates. La deuxième chaîne commence par un "3", donc la comparaison fonctionne comme "ordre alphabétique". Fait intéressant, ce type de comparaison fonctionne réellement (en quelque sorte par accident) si vous utilisez un format comme AAAA-MM-JJ. Mais bien sûr, il vaut mieux comparer les dates aux dates ...
Nick Perkins