mercredi 27 mai 2009

Intervalles de dates sous PostgreSQL et SQL Server

Quand j'ai commencé à programmer avec PostgreSQL, je sortais d'un environnement SQL Server et bien qu'il y ait des standards qui ne changent pas, je m'étonnais souvent de l'approche différente qu'avaient les deux SGBD. On le sait, Postgre a une tendance à suivre les traces d'Oracle alors que MSSQL le fait... à sa manière.

Dans SQL Server, si on veut ajouter un intervalle à une date, on doit utiliser la fonction DateAdd (inspirée de VBScript) en utilisant la forme : DateAdd(interval, number, date).
-- Ajouter 7 jours à la date
SELECT DateAdd("d", 7, "2009-05-27")
Sous PostgreSQL, c'est un peu plus subtil et on peut y arriver en utilisant plusieurs notations:
SELECT '2009-05-27'::date + 7
SELECT '2009-05-27'::date + interval '7 days'
SELECT '2009-05-27'::date + '7 days'::interval
Remarquez que l'opérateur "::" est utilisé pour la conversion de type, au même type que sa syntaxe équivalente CAST('2009-05-27' as date):
SELECT CAST('2009-05-27' as date) + 7
Ainsi, on peut convertir une chaîne de caractères en intervalle et l'utiliser comme s'il s'agissait du premier argument de DateAdd.
-- retourne 00:00:07
SELECT '7 seconds'::interval

-- retourne 00:10:00
SELECT '10 minutes'::interval

-- retourne 14:00:00
SELECT '14 hours'::interval
Maintenant qu'on comprend mieux les intervalles, plaçons en un dans un contexte pratique. Si on imagine un système de calendrier où chaque événement entré doit compter une date de fin calculée à 1 semaine plus tard, on pourrait faire quelque chose comme ceci:
SELECT date_event as date_start,
date_event + interval '1 week' as date_end
FROM calendar
Par contre, si la durée de l'intervalle se compte en jours et n'est pas fixe, on pourra la paramétrer, à l'aide d'une variable ou d'un champ de la table, qui composera l'intervalle:
UPDATE calendar
SET date_event = dt_event + (duration || ' days')::interval
Enfin, tant qu'à manipuler des intervalles, aussi bien en profiter pour montrer comment extraire une partie de la date (sous forme de timestamp - datetime en MSSQL):
-- 2009
SELECT EXTRACT(year FROM '2009-05-27 18:50:48.609-04'::timestamp)

-- 27
SELECT EXTRACT(day FROM '2009-05-27 18:50:48.609-04'::timestamp)

-- 18
SELECT EXTRACT(hour FROM '2009-05-27 18:50:48.609-04'::timestamp)
Vous l'aurez deviné, c'est l'équivalent PostgreSQL pour DatePart.

Aucun commentaire:

Publier un commentaire