Sie haben 1-01-01 ... 1-12-31
erwartet ... aber woher soll PostgreSQL wissen, was Sie damit meinen?
Literale Eingabezeichenfolgen werden gemäß den Einstellungen Ihrer aktuellen Sitzung interpretiert (die standardmäßig die allgemeinen Einstellungen in postgressql.conf
sind sofern nicht aufgehoben). Insbesondere datestyle
:
DateStyle
(string
)
Legt das Anzeigeformat für Datums- und Uhrzeitwerte sowie die Regeln für die Interpretation mehrdeutiger Datumseingabewerte fest. Aus historischen Gründen enthält diese Variable zwei unabhängige Komponenten:die Angabe des Ausgabeformats (ISO
, Postgres
, SQL
, oder German
) und die Eingabe-/Ausgabespezifikation für die Reihenfolge Jahr/Monat/Tag (DMY
, MDY
, oder YMD
). Diese können separat oder zusammen eingestellt werden. Die SchlüsselwörterEuro
und European
sind Synonyme für DMY
; die Schlüsselwörter US
,NonEuro
, und NonEuropean
sind Synonyme für MDY
. Siehe Abschnitt 8.5 für mehr Informationen. Der eingebaute Standard ist ISO, MDY
, aber initdb initialisiert die Konfigurationsdatei mit einer Einstellung, die dem Verhalten der gewählten lc_time
entspricht Gebietsschema.
(Während das Ausgabeformat hauptsächlich von lc_time
bestimmt wird .)
In Ihrem Fall das verstümmelte Zeitstempel-Literal 1-12-31 23:59:59
wird offensichtlich interpretiert als:
D-MM-YY h24:mi:ss
Während Sie gehofft hätten:
Y-MM-DD h24:mi:ss
3 Optionen
-
Legen Sie
datestyle
fest damit es Literale genauso interpretiert wie Sie. VielleichtISO, YMD
? -
Verwenden Sie
to_timestamp()
um das String-Literal wohldefiniert zu interpretieren - unabhängig von anderen Einstellungen. Viel besser.SELECT to_timestamp('1-12-31 23:59:59', 'Y-MM-DD h24:mi:ss');
-
Besser noch, verwenden Sie das ISO 8601-Format (
YYYY-MM-DD
) für alle datetime-Literale. Das ist eindeutig und unabhängig von jeglichen Einstellungen .SELECT '2001-12-31 23:59:59'::timestamp;
Abfrage neu schreiben
Ihre Abfrage ist zunächst fehlerhaft. Behandeln Sie Bereichsabfragen anders. Wie:
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;
Oder noch einfacher:
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;
Bereichstypen in PostgreSQL 9.2 oder neuer könnten von Interesse sein.