简体   繁体   English

为什么 -c 成功时 psql -f COPY FROM STDIN 会失败?

[英]Why does psql -f COPY FROM STDIN fail when -c succeeds?

Using psql with COPY FROM STDIN works fine when executed via -c (inline command) but the same thing fails if -f (script file) is used.通过-c (内联命令)执行时,将psqlCOPY FROM STDIN工作正常,但如果使用-f (脚本文件),同样的事情会失败。 I've created a Docker-based test to demonstrate below;我创建了一个基于 Docker 的测试来演示如下; tested on MacOS w/ zsh and Debian w/ bash.在带 zsh 的 MacOS 和带 bash 的 Debian 上测试。

I was unable to find any relevant documentation on why this would be but I imagine it has to do with psql 's special \\copy functionality.我找不到任何有关为什么会这样的相关文档,但我想这与psql的特殊\\copy功能有关。 Can someone help illuminate me?有人可以帮我照亮吗?

# create test data
echo "1,apple
2,orange
3,banana">testdata.csv

# create test script
echo "drop table if exists fruits;
create table fruits (id INTEGER, name VARCHAR);
copy fruits from stdin with delimiter as ',' csv;
select * from fruits">testscript.pg

# create network
docker network create pgtest

# run Postgres server
echo "starting postgres server"
PG_CONTAINER_ID=$(docker run -d --name=pgtest --rm --network=pgtest -h database -e POSTGRES_USER=user1 -e POSTGRES_PASSWORD=pass1 -e POSTGRES_DB=db1 -p 6432:5432 postgres:12)

echo "sleeping for 5 seconds (wait for server to start)"
sleep 5
docker logs $PG_CONTAINER_ID

echo "*"
echo "*"
echo "*"
echo "run psql script using inline with -c"
cat testdata.csv | docker run -i --rm --network=pgtest postgres:12 psql postgres://user1:pass1@database:5432/db1 -c "$(cat testscript.pg)"

echo "*"
echo "*"
echo "*"
echo "run psql script using file with -f"
cat testdata.csv | docker run -i -v $PWD:/host --rm --network=pgtest postgres:12 psql postgres://user1:pass1@database:5432/db1 -f /host/testscript.pg

# stop server
echo "*"
echo "*"
echo "*"
docker stop $PG_CONTAINER_ID
docker rm $PG_CONTAINER_ID

The output of the psql commands look like this: psql 命令的输出如下所示:

*
*
*
run psql script using inline with -c
NOTICE:  table "fruits" does not exist, skipping
 id |  name  
----+--------
  1 | apple
  2 | orange
  3 | banana
(3 rows)

*
*
*
run psql script using file with -f
DROP TABLE
CREATE TABLE
psql:/host/testscript.pg:5: ERROR:  invalid input syntax for type integer: "select * from fruits"
CONTEXT:  COPY fruits, line 1, column id: "select * from fruits"

In the first case, (execution with -c ), the copy data are read from standard input.在第一种情况下(使用-c执行),从标准输入读取复制数据。

In the second case (execution with -f ), the input file acts as input to psql (if you want, standard input is redirected from that file).在第二种情况下(使用-f执行),输入文件充当psql输入(如果需要,标准输入将从该文件重定向)。 So PostgreSQL interprets the rest of the file as COPY data and complains about the content.所以 PostgreSQL 将文件的其余部分解释为COPY数据并抱怨内容。 You'd have to mix the COPY data in with the file.您必须将COPY数据与文件混合。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM