Клиентская команда Postgres (\ copy) не имеет доступа к временной таблице?


9

Я генерирую список команд SQL для экспорта некоторых данных, которые в конечном итоге запускаю с помощью psql -f. Все запросы получают одно и то же подмножество данных, поэтому я решил выделить квалификацию и выложить список подходящих идентификаторов пользователей во временных таблицах, например

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

затем вернитесь к этому в моих командах \ copy, например

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

Все они находятся в одном файле, по одному на строку, и запускают их -f Я получаю сообщение об ошибке, что команды копирования не могут видеть временную таблицу, поэтому я предполагаю, что команда копирования клиента на самом деле не должна использовать один и тот же postgres. сессия как PSQL.

Это верно? Есть ли способ изменить это поведение?

Ответы:


16

\copy можно использовать временную таблицу.

Сначала я проверил и подтвердил это с помощью версии 9.0 в командной строке.
Затем я создал файл с мета-командой SQL и psql, \copyиспользуя несколько временных таблиц. Это сработало и для меня.

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

Вызов:

psql -p5432 mydb -f test.sql

Обратите внимание на завершающую точку с запятой, которая необязательна в конце файла (неявно завершается), но обязательна после любого другого оператора SQL, а также после последнего, если выполняется в psql в интерактивном режиме.

Обычно метакоманды psql нельзя смешивать с SQL в одной строке файла, выполняемого в psql -f. Я цитирую руководство по PSQL :

Разбор аргументов прекращается в конце строки или при обнаружении другого обратного слэша без кавычек. Обратная косая черта без кавычек принимается за начало новой мета-команды. Специальная последовательность \\(две обратные косые черты) отмечает конец аргументов и продолжает синтаксический анализ команд SQL, если таковые имеются. Таким образом, команды SQL и psql могут свободно смешиваться в строке. Но в любом случае аргументы метакоманды не могут продолжаться после конца строки.

Однако после этого применяются другие правила \copy. По сути, psql автоматически переключается в режим SQL после \copySee:

Но вы написали, что у вас есть все команды в отдельных строках. Так что это не может быть объяснением в вашем случае.


Помимо всего прочего, вы рассматривали возможность использования COPY(команда SQL ) вместо \copy( метакоманда psql )?

Конечно, в этом случае целевой файл должен быть локальным для сервера, а не для клиента. И разные файловые привилегии применяются. Руководство :

Файлы, названные в COPYкоманде, считываются или записываются непосредственно сервером, а не клиентским приложением. Поэтому они должны находиться или быть доступными для компьютера сервера базы данных, а не для клиента. Они должны быть доступны и доступны для чтения или записи пользователю PostgreSQL (идентификатор пользователя, под которым работает сервер), а не клиенту.


copy запускается от имени пользователя postgres, \ copy оборачивает copy для записи в std out и перенаправляется в файл, в который вы ее отправляете. Вы также можете вызвать psql, использовать \ o для отправки вывода в файл, а затем запустить копию на стандартный вывод, чтобы получить аналогичный эффект.
Скотт Марлоу

Чтобы убедиться, что я выполнил тест в своем ответе с суперпользователем (postgres) и фиктивным пользователем. Оба работают на меня. Те же результаты на v8.4.
Эрвин Брандштеттер

1
Да, может ли пользователь postgres unix получить доступ к таким вещам, как / tmp, зависит от того, установлен ли SELinux или нет, и позволяет ли он ему выходить из коробки. \ Copy или copy to stdout, безусловно, являются двумя более надежными способами использования copy.
Скотт Марлоу

1
Спасибо всем за ответы. Похоже, я забыл завершить строку, которая создала временную таблицу точкой с запятой, поэтому она не была создана. Работа, как и ожидалось сейчас
Jkebinger
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.