sql >> Base de Datos >  >> RDS >> PostgreSQL

PostgreSQL:entre con fecha y hora

Esperabas 1-01-01 ... 1-12-31 ... pero ¿cómo se supone que PostgreSQL sabe lo que quieres decir con eso?

Los literales de cadena de entrada se interpretan de acuerdo con la configuración de su sesión actual (que por defecto es la configuración general en postgressql.conf a menos que sea anulado). En particular datestyle :

DateStyle (string )

Establece el formato de visualización de los valores de fecha y hora, así como las reglas para interpretar valores de entrada de fecha ambiguos. Por razones históricas, esta variable contiene dos componentes independientes:la especificación del formato de salida (ISO , Postgres , SQL , o German ) y la especificación de entrada/salida para la ordenación por año/mes/día (DMY , MDY ,o YMD ). Estos se pueden configurar por separado o juntos. Las palabras claveEuro y European son sinónimos de DMY; las palabras clave US ,NonEuro y NonEuropean son sinónimos de MDY . Ver Sección 8.5 para más información. El valor predeterminado incorporado es ISO, MDY , pero initdb inicializará el archivo de configuración con una configuración que corresponde al comportamiento del lc_time elegido configuración regional.

(Mientras que el formato de salida está determinado principalmente por lc_time .)

En su caso, el literal de marca de tiempo mutilado 1-12-31 23:59:59 obviamente se interpreta como:

D-MM-YY h24:mi:ss

Si bien hubieras esperado:

Y-MM-DD h24:mi:ss

3 opciones

  1. Establecer datestyle para que interprete los literales de la misma manera que tú. Quizás ISO, YMD ?

  2. Usa to_timestamp() para interpretar el literal de la cadena de una manera bien definida, independientemente de otras configuraciones. Mucho mejor.

     SELECT to_timestamp('1-12-31 23:59:59', 'Y-MM-DD h24:mi:ss');
    
  3. Mejor aún, utilice el formato ISO 8601 (YYYY-MM-DD ) para todos los literales de fecha y hora. Eso es inequívoco e independiente de cualquier configuración .

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

Reescribir consulta

Su consulta es incorrecta para empezar. Maneje las consultas de rango de manera diferente. Me gusta:

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;

O, más simple aún:

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;

Los tipos de rango en PostgreSQL 9.2 o posterior pueden ser de interés.