PostgreSQL中COPY命令中动态生成的表名

6
这个 PostgreSQL 的 COPY 命令可以正常工作:
copy tablename from E'c:\\abc\\a.txt';

但是我希望表名可以动态生成。我该如何做到这一点?

2个回答

16

您需要构建一个字符串,将动态表名连接起来,然后使用execute。请注意,您需要用''来转义'。这还包括一个动态名称来保存文件。您需要用实际目录替换savedir。

CREATE OR REPLACE FUNCTION dynamicCopy(tablename text, outname text) RETURNS VOID AS $$

DECLARE STATEMENT TEXT;

BEGIN

  STATEMENT := 'COPY (select * from ' || quote_ident(tablename) || ') to ''savedir' || outname ||'.txt''';

  EXECUTE STATEMENT;

END;

$$ LANGUAGE 'plpgsql';

编辑:

自从我第一次写这篇文章以来,我已经发现了format函数,我认为它通常比使用连接运算符||生成的SQL更易于阅读并且更灵活。

CREATE OR REPLACE FUNCTION dynamicCopy(tablename text, outname text) RETURNS VOID AS 
$BODY$
BEGIN
  EXECUTE FORMAT('COPY (SELECT * FROM %s) TO ''savedir%s.csv''',
                  tablename, 
                  outname);
END
$BODY$ 
LANGUAGE plpgsql;

请查看官方文档以获取详细讨论: https://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN


3
你的示例代码实际上演示了动态生成文件名,而不是动态生成表名。此外,你没有提到你的示例代码指定逗号分隔输出,而不是默认的制表符分隔输出。(你是从别处复制你的示例代码吗?) - ruakh
Ruakh,感谢您指出错误。现在已经使用动态表名和文件名进行了编辑。是的,这只是我在工作中使用的某个东西的大大简化版本——我将来会更加小心地正确回答问题。 - John Powell
天啊,我花了一些时间才发现 quot_ident 中的拼写错误!实际上应该是 quotE_ident!现在这个错误有意义了:“pg_execute():查询失败:ERROR:42883:函数 quot_ident(text) 不存在”。 - Vadim Samokhin

0

你可以通过shell脚本从多个CSV文件复制到一个表中。

  1. 创建一个脚本文件:vim csvtotable

  2. 编写csvtotable脚本。以下是我的示例:

    #!/bin/sh DBNAME=postgres files=$1 for file in ${files}; do psql -d ${DBNAME} -c "\copy parent_tree(parent_id, some_text) FROM '${file}' delimiters ',' csv header" done

  3. 执行脚本。

    ./csv2table "$(ls *.out.csv)"

显然,本地CSV文件应该与表格匹配。如果CSV文件名以.out.csv结尾,则会将其从CSV导入到数据库表中。 我不确定CSV名称匹配是全局的还是只在当前目录匹配。 参考链接:
-c 命令参考 https://www.postgresql.org/docs/current/app-psql.html#APP-PSQL-PATTERNS chomd 命令:https://linuxize.com/post/chmod-command-in-linux/
bash shanebang:https://linuxize.com/post/bash-shebang/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接