Cómo especificar el parámetro PSYCOPG2 para una matriz para marcas de tiempo (a veces)
-
22-09-2019 - |
Pregunta
Me gustaría ejecutar una consulta PostgreSQL en Python usando PSYCOPG2, que filtra por una columna de tipo timestamp without timezone
. Tengo una larga lista de valores permitidos para la marca de tiempo (en lugar de un rango) y PSYCOPG2 manejan convenientemente las matrices, por lo que pensé que esto debería funcionar:
SELECT somestuff
FROM mytable
WHERE thetimestamp = ANY (%(times)s)
los times
El parámetro es una lista de datetime
objetos. También he probado psycopg2.Timestamp()
. Ambos se traducen a WHERE thetimestamp = ANY (ARRAY['2009-07-06T00:00:00', '2009-07-07T00:00:00', ...])
Y desafortunadamente eso falla con el siguiente error:
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.
También confirmé esto en Pgadmin, por lo que no es solo PSYCOPG2. Lo que parece estar sucediendo es que Postgres no convertirá implícitamente una variedad de cuerdas en una variedad de marcas de tiempo. Convertirá una sola cadena fina y la matriz funciona bien si agrego explícitamente ::timestamp
a cada elemento en Pgadmin, pero no sé cómo hacerlo en PsyCopg2.
¿Cuál es la mejor manera de hacer esto, aparte de olvidar los parámetros DB-API y simplemente construir la larga cadena de marcas de tiempo manualmente? ¿Hay alguna forma de que pueda lanzarlo al tipo correcto?
Solución
Pruébelo así:
SELECT somestuff
FROM mytable
WHERE thetimestamp = ANY (%(times)s::timestamp[])
Otros consejos
Si usa PSYCOPG2 versión 2.2.0 o más nuevo, su código original debería funcionar, si envuelve los valores en Timestamp()
constructores, como sugeriste.
La razón por la que no funcionó antes fue un error en la implementación de PSYCOPG2. La solución sugerida era insertar moldes explícitos en el SQL, como se sugiere en otra respuesta.