Ajouter un intervalle à une donnée temporelle
Avec Oracle Database, il est courant de voir des syntaxes du style sysdate + 1 ou current_timestamp + 1/2 pour ajouter un intervalle à une donnée temporelle. Que signifient ces syntaxes ?
Démonstration avec Oracle Database 11.2.0.2 :
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
SQL> select to_char(current_date,'DD/MM/YY HH24:MI') as hui, to_char(current_date + 1/1440,'DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(current_date+1, 'DD/MM/YY HH24:MI') as demain from dual;
HUI UNE_MINUTE_PLUS DEMAIN
-------------- --------------- --------------
18/12/16 11:54 18/12/16 11:55 19/12/16 11:54
SQL> select to_char(current_timestamp,'DD/MM/YY HH24:MI') as hui, to_char(current_timestamp + 1/1440,'DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(current_timestamp+1, 'DD/MM/YY HH24:MI') as demain from dual;
HUI UNE_MINUTE_PLUS DEMAIN
-------------- --------------- --------------
18/12/16 13:50 18/12/16 13:51 19/12/16 13:50
SQL> select to_char(current_timestamp,'DD/MM/YY HH24:MI') as hui, to_char(current_timestamp + 1/1440,'DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(current_timestamp+1, 'DD/MM/YY HH24:MI') as demain from dual;
HUI UNE_MINUTE_PLUS DEMAIN
-------------- --------------- --------------
18/12/16 13:50 18/12/16 13:51 19/12/16 13:50
SQL> select to_char(sysdate,'DD/MM/YY HH24:MI') as hui, to_char(sysdate + 1/1440,'DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(sysdate+1, 'DD/MM/YY HH24:MI') as demain from dual;
HUI UNE_MINUTE_PLUS DEMAIN
-------------- --------------- --------------
18/12/16 13:51 18/12/16 13:52 19/12/16 13:51
SQL> select to_char(systimestamp,'DD/MM/YY HH24:MI') as hui, to_char(systimestamp + 1/1440,'DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(systimestamp+1, 'DD/MM/YY HH24:MI') as demain from dual;
HUI UNE_MINUTE_PLUS DEMAIN
-------------- --------------- --------------
18/12/16 13:51 18/12/16 13:52 19/12/16 13:51
Que peut-on tirer de ces quelques commandes ? Oracle accepte dajouter des valeurs entières ou fractionnaires à des données de type DATE ou TIMESTAMP. Les valeurs ajoutées sont considérées en JOURS. Par exemple, 1/1440 représente 1 minute.
Place à présent à PostgreSQL dans sa version 9.6 :
select version();
version
---------------------------------------------------------------------------------------------------
PostgreSQL 9.6.1 on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.2.0-10) 6.2.0 20161027, 64-bit
(1 ligne)
select to_char(current_date,'DD/MM/YY HH24:MI') as hui, to_char(current_date + 1/1440,'DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(current_date+1, 'DD/MM/YY HH24:MI') as demain ;
hui | une_minute_plus_tard | demain
----------------+----------------------+----------------
18/12/16 00:00 | 18/12/16 00:00 | 19/12/16 00:00
(1 ligne)
select to_char(current_timestamp,'DD/MM/YY HH24:MI') as hui, to_char(current_timestamp + 1/1440,'DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(current_timestamp+1, 'DD/MM/YY HH24:MI') as demain ;
ERREUR: lopérateur nexiste pas : timestamp with time zone + integer
LIGNE 1 : ...MM/YY HH24:MI') as hui, to_char(current_timestamp + 1/1440,'...
^
ASTUCE : Aucun opérateur ne correspond au nom donné et aux types d'arguments.
Vous devez ajouter des conversions explicites de type.
select to_char(current_timestamp,'DD/MM/YY HH24:MI') as hui, to_char(current_timestamp + interval '1 minute','DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(current_timestamp + interval '1 day', 'DD/MM/YY HH24:MI') as demain ;
hui | une_minute_plus_tard | demain
----------------+----------------------+----------------
18/12/16 04:41 | 18/12/16 04:42 | 19/12/16 04:41
(1 ligne)
select to_char(current_timestamp,'DD/MM/YY HH24:MI') as hui, to_char(current_timestamp + cast('1 minute' as interval),'DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(current_timestamp + cast('1 day' as interval), 'DD/MM/YY HH24:MI') as demain ;
hui | une_minute_plus_tard | demain
----------------+----------------------+----------------
18/12/16 04:44 | 18/12/16 04:45 | 19/12/16 04:44
(1 ligne)
select to_char(current_timestamp,'DD/MM/YY HH24:MI') as hui, to_char(current_timestamp + interval '1' minute,'DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(current_timestamp + interval '1' day, 'DD/MM/YY HH24:MI') as demain ;
hui | une_minute_plus_tard | demain
----------------+----------------------+----------------
18/12/16 04:46 | 18/12/16 04:47 | 19/12/16 04:46
(1 ligne)
Les DATES Oracle ont une précision à la seconde, les DATES PostgreSQL sont précises à la journée. Ajouter un entier à une DATE est donc accepté par PostgreSQL. Il ny a aucune ambiguïté : il sagit dajouter un intervalle exprimé en JOURS à cette DATE.
En revanche, il est impossible dajouter un entier ou autre valeur numérique à un TIMESTAMP avec PostgreSQL. Il faut ajouter un INTERVAL et plusieurs syntaxes sont acceptées.
Une ou plusieurs de ces syntaxes sont-elles acceptées par Oracle Database ? Démonstration avec Oracle Database 11.2.0.2 :
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
SQL> select to_char(current_timestamp,'DD/MM/YY HH24:MI') as hui, to_char(current_timestamp + interval '1 minute','DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(current_timestamp + interval '1 day', 'DD/MM/YY HH24:MI') as demain
from dual;
select to_char(current_timestamp,'DD/MM/YY HH24:MI') as hui, to_char(current_timestamp + interval '1 minute','DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(current_timestamp + interval '1 day',
'DD/MM/YY HH24:MI') as demain from dual
*
ERROR at line 1:
ORA-30089: missing or invalid datetime field
SQL> select to_char(current_timestamp,'DD/MM/YY HH24:MI') as hui, to_char(current_timestamp + cast('1 minute' as interval),'DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(current_timestamp + cast('1 day' as interval), 'DD/MM/YY
HH24:MI') as demain ;
select to_char(current_timestamp,'DD/MM/YY HH24:MI') as hui, to_char(current_timestamp + cast('1 minute' as interval),'DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(current_timestamp + cast('1 d
ay' as interval), 'DD/MM/YY HH24:MI') as demain
*
ERROR at line 1:
ORA-30089: missing or invalid datetime field
SQL> select to_char(current_timestamp,'DD/MM/YY HH24:MI') as hui, to_char(current_timestamp + interval '1' minute,'DD/MM/YY HH24:MI') as une_minute_plus_tard, to_char(current_timestamp + interval '1'
day, 'DD/MM/YY HH24:MI') as demain from dual;
HUI UNE_MINUTE_PLUS DEMAIN
-------------- --------------- --------------
18/12/16 12:11 18/12/16 12:12 19/12/16 12:11
Bingo ! Au moins une des syntaxes permettant dajouter un INTERVAL à un TIMESTAMP est acceptée par PostgreSQL comme Oracle. Il est donc possible, si vous le souhaitez, de produire un code commun sur cet aspect avec ces 2 SGBD.
Mise à jour : 18/12/2016