web-dev-qa-db-fra.com

Oracle: Comment sélectionner la date du jour (aujourd'hui) avant minuit?

Avec Oracle, comment sélectionnez-vous la date actuelle (à savoir SYSDATE) à 11:59:59?

Tenez compte du fait que la définition de minuit peut être un peu ambiguë (jeudi minuit signifie Straddling jeudi et vendredi ou Straddling mercredi et jeudi?).

7
gaboroncancio

Pour sélectionner la date actuelle (aujourd'hui) avant minuit (une seconde avant), vous pouvez utiliser l'une des déclarations suivantes:

SELECT TRUNC(SYSDATE + 1) - 1/(24*60*60) FROM DUAL
SELECT TRUNC(SYSDATE + 1) - INTERVAL '1' SECOND FROM DUAL;

Ce qu'il fait:

  1. Somme d'un jour à SYSDATE: SYSDATE + 1, maintenant la date est demain
  2. Supprimer l'heure dans la partie de la date avec TRUNC, maintenant la date est demain à 00:00
  3. Soustrayez une seconde de la date: - 1/(24*60*60) ou - INTERVAL '1' SECOND FROM DUAL, la date est aujourd'hui à 11:59:59.

Remarque 1: Si vous souhaitez vérifier les intervalles de dates, vous pouvez également vérifier la réponse @Allan ci-dessous.

Note 2: Comme alternative, vous pouvez utiliser cet autre (qui est plus facile à lire):

SELECT TRUNC(SYSDATE) + INTERVAL '23:59:59'  HOUR TO SECOND FROM DUAL;
  1. Supprimer l'heure de la date actuelle avec TRUNC, maintenant la date est aujourd'hui à 00:00
  2. Ajoutez un intervalle de temps de 23:59:59, la date est aujourd'hui à 11:59:59.

Note 3: Pour vérifier les résultats, vous pouvez vouloir ajouter le format:

SELECT TO_CHAR(TRUNC(SYSDATE + 1) - 1/(24*60*60),'yyyy/mm/dd hh24:mi:ss') FROM DUAL
SELECT TO_CHAR(TRUNC(SYSDATE + 1) - INTERVAL '1' SECOND,'yyyy/mm/dd hh24:mi:ss') FROM DUAL
SELECT TO_CHAR(TRUNC(SYSDATE) + INTERVAL '23:59:59','yyyy/mm/dd hh24:mi:ss') FROM DUAL
11
gaboroncancio

Personnellement, je n'aime pas utiliser une seconde avant minuit. Entre autres choses, si vous utilisez une timestamp, il est possible que la valeur que vous comparez se situe entre les espaces (c.-à-d. 23: 59: 59.1). Étant donné que ce type de logique est généralement utilisé comme limite pour une condition de plage, je suggérerais d'utiliser "moins que minuit", plutôt que "moins ou égal à une seconde avant minuit" si possible. La syntaxe pour cela simplifie également. Par exemple, pour obtenir un intervalle de temps représentant "aujourd'hui", vous pouvez utiliser l'un des éléments suivants:

date_value >= trunc(sysdate) and date_value < trunc(sysdate) + 1
date_value >= trunc(sysdate) and date_value < trunc(sysdate) + interval '1' day

C'est un peu plus encombrant que d'utiliser between, mais cela vous évite d'avoir une valeur qui ne dépasse pas la plage que vous envisagez.

8
Allan

La vraie ambiguïté réside probablement dans secondes intercalaires et peut-être même l'heure d'été (mais je ne sais pas s'il existe des cas où cela change à minuit ou non).

Quoi qu'il en soit, pour le cas habituel, il y a peu de solutions:

-- all of these will produce a `DATE` result:
SELECT TRUNC(SYSDATE+1)-1/86400 FROM DUAL;
SELECT TRUNC(SYSDATE+1) - INTERVAL '1' SECOND FROM DUAL;
SELECT TRUNC(SYSDATE) + INTERVAL '23:59:59'  HOUR TO SECOND FROM DUAL;

Quelques petites bizarreries si vous utilisez des horodatages:

  • TRUNC convertira silencieusement la valeur en DATE;
  • Ajouter/soustraire une NUMBER à/d'une TIMESTAMP produira aussi DATE. Voir Arithmétique Datetime/Interval pour les détails.
-- those two will produce a `DATE` *too*, not a `TIMESTAMP`:
SELECT TRUNC(SYSTIMESTAMP) + INTERVAL '23:59:59'  HOUR TO SECOND FROM DUAL;

SELECT TO_TIMESTAMP(TRUNC(SYSTIMESTAMP+1))-1/86400 FROM DUAL;
3
Sylvain Leroux