Come specificare il parametro PsyCOPG2 per un array per i timestamp (DateTimes)
-
22-09-2019 - |
Domanda
Vorrei eseguire una query PostgreSQL in Python usando Psycopg2, che filtra per una colonna di tipo timestamp without timezone
. Ho un lungo elenco di valori consentiti per il timestamp (anziché un intervallo) e Psycopg2 gestisce comodamente array, quindi ho pensato che questo dovesse funzionare:
SELECT somestuff
FROM mytable
WHERE thetimestamp = ANY (%(times)s)
Il times
Il parametro è un elenco di datetime
oggetti. Ho anche provato psycopg2.Timestamp()
. Entrambi si traducono in WHERE thetimestamp = ANY (ARRAY['2009-07-06T00:00:00', '2009-07-07T00:00:00', ...])
E sfortunatamente questo fallisce con il seguente errore:
operator does not exist: timestamp without time zone = text
LINE 3: WHERE thetimestamp = ANY (ARRAY['2009-07-06T00:00:00', '2009-07-07T00:00:00', ...]
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
L'ho confermato anche in pgadmin, quindi non è solo Psycopg2. Ciò che sembra accadere è che Postgres non convertirà implicitamente una serie di stringhe in una serie di timestamp. Convertirà una sola stringa e l'array funziona bene se aggiungo esplicitamente ::timestamp
Ad ogni elemento in PGADMIN, ma non so come farlo in Psycopg2.
Qual è il modo migliore per farlo, oltre a dimenticare i parametri DB-API e costruire manualmente la lunga serie di timestamp? C'è un modo per farlo lanciare al tipo corretto?
Soluzione
Provalo in questo modo:
SELECT somestuff
FROM mytable
WHERE thetimestamp = ANY (%(times)s::timestamp[])
Altri suggerimenti
Se si utilizza PsyCOPG2 versione 2.2.0 o più recente, il codice originale dovrebbe funzionare, se si avvolgono i valori in Timestamp()
costruttori, come hai suggerito.
Il motivo per cui non funzionava prima era un bug nell'implementazione di Psycopg2. La soluzione suggerita era quella di inserire cast espliciti nel SQL, come suggerito in un'altra risposta.