Postgres客户端复制(\ copy)命令没有访问临时表的权限?


9

我正在生成SQL命令列表,以导出一些最终使用psql -f运行的数据。所有查询都获得相同的数据子集,所以我认为我会考虑将资格限定在内,并在诸如此类的临时表中放入合格用户ID的列表。

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。

那是对的吗?有没有办法改变这种行为?

Answers:


16

\copy 可以使用临时表。

首先,我在命令行上使用9.0版进行了测试并确认了这一点。
然后,我\copy使用多个临时表通过SQL和psql meta命令创建了一个文件。这也对我有用。

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混合在per所执行的文件中的同一行psql -f。我引用有关psql手册

对参数的解析在该行的结尾处停止,或者在找到另一个未引用的反斜杠时停止。不带引号的反斜杠被视为新元命令的开始。特殊序列\\(两个反斜杠)标记参数的结尾,并继续解析SQL命令(如果有)。这样,SQL和psql命令可以自由地混合在一行上。但是无论如何,元命令的参数不能超出该行的末尾。

适用不同的规则 \copy,虽然。本质上,\copy请参阅以下内容,psql会自动切换回SQL模式:

但是您写了所有命令都放在单独的行上。因此,这不可能是您情况下的解释。


除此之外,您是否考虑过使用COPYSQL命令)代替\copypsql meta-command)?

当然,在这种情况下,目标文件必须是服务器本地的,而不是客户端本地的。并且应用了不同的文件特权。手册

COPY命令中命名的文件由服务器而不是客户端应用程序直接读取或写入。因此,它们必须驻留在数据库服务器计算机(而不是客户端)上或可被其访问。PostgreSQL用户(服务器运行时使用的用户ID),而不是客户端,必须可以访问它们并对其进行读写。


copy以postgres用户身份运行,\ copy包装复制的副本以将其写入std并重定向到您发送至的文件。您也可以调用psql,使用\ o将输出发送到文件,然后运行副本到stdout以获得类似的效果。
Scott Marlowe

可以肯定的是,我是在超级用户(postgres)和虚拟用户的答案中进行测试的。两者都为我工作。在v8.4上结果相同。
Erwin Brandstetter

1
是的,postgres UNIX用户是否可以访问/ tmp之类的内容取决于SELinux是否已安装以及是否允许其开箱即用。\ copy或复制到stdout绝对是使用copy的两种更可靠的方法。
Scott Marlowe

1
谢谢大家的回答。似乎我忽略了用分号创建临时表的行的结尾,因此未创建该表。现在按预期工作
jkebinger 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.