为什么从 PL/pqSQL 函数调用时 \COPY 不起作用?

Mar*_*dik 2 postgresql psql

我正在尝试使用该\COPY函数从客户端的文本文件填充数据库。我正在使用Postgres 交互式终端(psql) 来执行此任务。

我编写了以下脚本并将其保存到test.sql

CREATE FUNCTION copy_stuff_to_db(path text, encoding text) RETURNS void
AS $$
BEGIN
    \COPY table1 FROM path || 'table1.asc' WITH ENCODING encoding;
END;
$$ LANGUAGE plpgsql;

PERFORM copy_stuff_to_db('/home/martin', 'ISO 8859-1')
Run Code Online (Sandbox Code Playgroud)

我是这样执行的:

psql --port 5432 --host localhost -d mydb --username postgres -f test.sql 
Run Code Online (Sandbox Code Playgroud)

但我收到一个错误:

psql:test.sql:12: ERROR:  syntax error at or near "\" 
LINE 4: \COPY table1 FROM path || 'table1.asc' WITH DE...
        ^
Run Code Online (Sandbox Code Playgroud)

起初我认为终端不执行 PL/pgSQL,我将不得不放置我的文件并运行脚本服务器端。但是,当我直接调用该函数时(即我将之前的脚本修改为):

\COPY table1 FROM '/home/martin/table1.asc' WITH ENCODING 'ISO 8859-1';
Run Code Online (Sandbox Code Playgroud)

然后一切正常。\COPY由于某种原因,从另一个函数调用时,该函数似乎不起作用。

我究竟做错了什么?

mus*_*cio 5

TLDR:\copypsql指令,不是 PL/pgSQL 命令。它不能由服务器解释,只能由psql客户端本身解释。


psql客户端,任何其他数据库客户端软件,非常有限的能力。它本身不能读取或写入表行(因为它们在物理上位于数据库服务器)、执行存储过程和函数(因为它们再次驻留在服务器上并在服务器上执行)等。它所能做的就是发送向服务器发送 SQL 命令并将其结果呈现给用户。

举个例子,当你输入select foo from barpsql,并按Enter,客户端打开的游标对于给定的查询文本,让服务器进程查询,获取结果集,并显示给你以某种方式格式化。

回到\copy,这是文档必须说的内容

不要COPY与 psql 指令混淆\copy\copy调用COPY FROM STDINor COPY TO STDOUT,然后在 psql 客户端可访问的文件中获取/存储数据。

同样,当您使用psql包含函数定义的脚本文件执行时:

CREATE FUNCTION copy_stuff_to_db(path text, encoding text) RETURNS void
AS $$
BEGIN
    \COPY table1 FROM path || 'table1.asc' WITH ENCODING encoding;
END;
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

它(psql)实际上并没有执行任何这些;它将代码作为单个语句发送到服务器进行处理。服务器尝试将其解析为 PL/pgSQL 代码(因为LANGUAGE plpgsql)、编译并存储在数据库中以供将来调用。由于\COPY不是有效的 PL/pgSQL 命令,编译失败并显示您看到的错误。

附注。其他人可能会纠正我,但我认为即使使用正确的COPY命令,您也无法在函数中实现您想要的功能,因为它需要动态 SQL,我认为它不能与COPY.