El comando postgres client copy (\ copy) no tiene acceso a una tabla temporal?

9

Estoy generando una lista de comandos SQL para exportar algunos datos que finalmente ejecuto usando psql -f. Todas las consultas obtienen el mismo subconjunto de datos, así que pensé en factorizar las calificaciones y poner una lista de identificadores de usuario elegibles en tablas temporales como esta

create temporary table tmp_export_users as (select id from users where ...)

luego consulte de nuevo en mis comandos \ copy como

\copy (select ... from table where user_id in (select id from tmp_export_users)) TO 'filename.csv' WITH CSV HEADER

Todos están en el mismo archivo, uno por línea, y los ejecutan. Si recibo el error de que los comandos de copia no pueden ver la tabla temporal, supongo que el comando de copia del cliente no debe usar los mismos postgres. sesión como psql.

¿Es eso correcto? ¿Hay alguna manera de cambiar ese comportamiento?

jkebinger
fuente

Respuestas:

16

\copy puede usar una tabla temporal.

Primero probé y confirmó esto con la versión 9.0 en la línea de comando.
Luego creé un archivo con metacomando SQL y psql \copyusando múltiples tablas temporales. También funcionó para mí.

CREATE TEMP TABLE tmp as SELECT * FROM tbl;
\copy (SELECT * FROM tmp JOIN tbl USING (id)) TO '/var/lib/postgres/test1.csv';

Llamada:

psql -p5432 mydb -f test.sql

Tenga en cuenta el punto y coma de terminación, que es opcional al final de un archivo (terminado implícitamente), pero se requiere después de cualquier otra instrucción SQL y también después de la última si se ejecuta en psql de forma interactiva.

Normalmente , los metacomandos psql no se pueden mezclar con SQL en la misma línea en un archivo ejecutado por psql -f. Cito el manual en psql :

El análisis de argumentos se detiene al final de la línea o cuando se encuentra otra barra invertida sin comillas. Una barra invertida sin comillas se toma como el comienzo de un nuevo metacomando. La secuencia especial \\(dos barras invertidas) marca el final de los argumentos y continúa analizando los comandos SQL, si los hay. De esa manera, los comandos SQL y psql se pueden mezclar libremente en una línea. Pero, en cualquier caso, los argumentos de un metacomando no pueden continuar más allá del final de la línea.

Sin embargo, se aplican diferentes reglas después \copy . Esencialmente, psql vuelve al modo SQL automáticamente después de \copyVer:

Pero usted escribió que tenía todos los comandos en líneas separadas. Entonces esa no puede ser la explicación en su caso.


Aparte de eso, ¿ha considerado usar COPY(el comando SQL ) en lugar de \copy(el metacomando psql )?

Por supuesto, el archivo de destino tendría que ser local para el servidor y no para el cliente en este caso. Y se aplican diferentes privilegios de archivo. El manual :

Los archivos nombrados en un COPYcomando son leídos o escritos directamente por el servidor, no por la aplicación cliente. Por lo tanto, deben residir o ser accesibles para la máquina del servidor de la base de datos, no para el cliente. Deben ser accesibles para que el usuario de PostgreSQL pueda leerlos o escribirlos (el ID de usuario con el que se ejecuta el servidor), no el cliente.

Erwin Brandstetter
fuente
copy se ejecuta como el usuario de postgres, \ copy wraps copy to write to std out y se redirige al archivo al que lo envía. También puede llamar a psql, usar \ o para enviar la salida a un archivo y luego ejecutar una copia en stdout para obtener un efecto similar.
Scott Marlowe
Para estar seguro, ejecuté la prueba en mi respuesta con un superusuario (postgres) y un usuario ficticio. Ambos trabajan para mi. Los mismos resultados en v8.4.
Erwin Brandstetter
1
Sí, si el usuario de Postgres Unix puede acceder a cosas como / tmp depende de cosas como si SELinux está instalado o no y si lo deja fuera de su caja. \ Copy o copy to stdout son definitivamente las dos formas más confiables de usar copy.
Scott Marlowe, el
1
Gracias por las respuestas a todos. Parece que olvidé terminar la línea que creó una tabla temporal con un punto y coma, por lo que no se creó. Trabajando como se esperaba ahora
jkebinger