PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

PostgreSQL :entre avec datetime

Vous attendiez 1-01-01 ... 1-12-31 ... mais comment PostgreSQL est-il censé savoir ce que vous entendez par là ?

Les littéraux de chaîne d'entrée sont interprétés en fonction des paramètres de votre session actuelle (qui sont par défaut les paramètres généraux dans postgressql.conf sauf dérogation). En particulier datestyle :

DateStyle (string )

Définit le format d'affichage des valeurs de date et d'heure, ainsi que les règles d'interprétation des valeurs d'entrée de date ambiguës. Pour des raisons historiques, cette variable contient deux composants indépendants :la spécification du format de sortie (ISO , Postgres , SQL , ou German ) et la spécification d'entrée/sortie pour la commande année/mois/jour (DMY , MDY ,ou YMD ). Ceux-ci peuvent être réglés séparément ou ensemble. Les mots-clés Euro et European sont synonymes de DMY; les mots clés US ,NonEuro , et NonEuropean sont synonymes de MDY . Voir Section 8.5 pour plus d'informations. La valeur par défaut intégrée est ISO, MDY , mais initdb initialisera le fichier de configuration avec un paramètre qui correspond au comportement du lc_time choisi locale.

(Alors que le format de sortie est principalement déterminé par lc_time .)

Dans votre cas, le littéral d'horodatage mutilé 1-12-31 23:59:59 est évidemment interprété comme :

D-MM-YY h24:mi:ss

Alors que vous auriez espéré :

Y-MM-DD h24:mi:ss

3 options

  1. Définir datestyle afin qu'il interprète les littéraux de la même manière que vous. Peut-être ISO, YMD ?

  2. Utilisez to_timestamp() pour interpréter la chaîne littérale d'une manière bien définie - indépendamment des autres paramètres. Beaucoup mieux.

     SELECT to_timestamp('1-12-31 23:59:59', 'Y-MM-DD h24:mi:ss');
    
  3. Mieux encore, utilisez le format ISO 8601 (YYYY-MM-DD ) pour tous les littéraux datetime. C'est sans ambiguïté et indépendant de tout paramètre .

     SELECT '2001-12-31 23:59:59'::timestamp;
    

Réécrire la requête

Votre requête est erronée pour commencer. Gérez les requêtes de plage différemment. Comme :

SELECT d.given_on 
FROM   documents_document d
WHERE  EXTRACT('month' FROM d.given_on) = 1
AND    d.given_on >= '2001-01-01 0:0'
AND    d.given_on <  '2002-01-01 0:0'
ORDER  BY d.created_on DESC;

Ou, plus simple encore :

SELECT d.given_on 
FROM   documents_document d
WHERE  d.given_on >= '2001-01-01 0:0'
AND    d.given_on <  '2001-02-01 0:0'
ORDER  BY d.created_on DESC;

Les types de plage dans PostgreSQL 9.2 ou plus récent peuvent être intéressants.