如何从 PostgreSQL 转储表的一部分?

Leo*_*sov 16 postgresql sql

我有一个带有多 Gb 表(其中包含某些事件的日志)的 PostgreSQL 数据库。我需要将最新事件传递给分析师 - 假设他只需要上个月的事件。

我怎样才能产生只有那些行的转储,比如说,created_at > '2012-05-01'

Mil*_*dev 16

另一种方法是使用COPY\copypsql命令),例如:

COPY (SELECT * FROM big_table WHERE created_at > '2012-05-01') TO '/path/to/a/dump/file';
Run Code Online (Sandbox Code Playgroud)

  • 但是它会产生实际的 INSERT 语句吗?更一般地说,您如何将转储返回到数据库中? (5认同)
  • 来自[这个答案](http://stackoverflow.com/a/1746215/1098603)的@LeonidShevtsov你可以`COPY big_table FROM '/path/to/a/dump/file`,尽管你可能必须有相同的两个实例上的版本。 (3认同)

gil*_*905 11

psql -c "COPY (SELECT * FROM my_table WHERE created_at > '2012-05-01') TO STDOUT;" source_db | psql -c "COPY my_table FROM STDIN;" target_db


小智 7

免责声明:逐字来自/sf/ask/106234481/

您想要在服务器上还是在客户端上的结果文件?

服务器端

如果你想要一些易于重用或自动化的东西,你可以使用 Postgresql 的内置COPY命令。例如

Copy (Select * From foo) To '/tmp/test.csv' With CSV DELIMITER ',';
Run Code Online (Sandbox Code Playgroud)

这种方法完全在远程服务器上运行——它不能写入您的本地 PC。它还需要以 Postgres“超级用户”(通常称为“root”)的身份运行,因为 Postgres 无法阻止它使用该机器的本地文件系统做令人讨厌的事情。

这实际上并不意味着您必须以超级用户身份进行连接(自动化会带来不同类型的安全风险),因为您可以使用SECURITY DEFINER选项CREATE FUNCTION来创建一个像超级用户一样运行的功能。

关键部分是您的函数在那里执行额外的检查,而不仅仅是绕过安全性 - 因此您可以编写一个函数来导出您需要的确切数据,或者您可以编写一些可以接受各种选项的函数,只要它们满足严格的白名单。你需要检查两件事:

  1. 应该允许用户在磁盘上读/写哪些文件?例如,这可能是一个特定的目录,并且文件名可能必须具有合适的前缀或扩展名。
  2. 用户应该能够在数据库中读/写哪些?这通常由GRANT数据库中的s定义,但该函数现在以超级用户身份运行,因此通常“越界”的表将完全可以访问。您可能不想让某人调用您的函数并在“用户”表的末尾添加行……

我写了一篇扩展这种方法的博客文章,包括一些导出(或导入)满足严格条件的文件和表的函数示例。


客户端

另一种方法是在客户端进行文件处理,即在您的应用程序或脚本中。Postgres 服务器不需要知道您要复制到哪个文件,它只是吐出数据,然后客户端将其放在某处。

它的底层语法是COPY TO STDOUT命令,像 pgAdmin 这样的图形工具会在一个漂亮的对话框中为你包装它。

psql命令行客户端有一个特殊的“元命令”之称\copy,这需要所有相同的选项,“真正的” COPY,但在运行客户端中:

\copy (Select * From foo) To '/tmp/test.csv' With CSV
Run Code Online (Sandbox Code Playgroud)

请注意,没有终止;,因为元命令以换行符终止,与 SQL 命令不同。

文档

不要将 COPY 与 psql 指令 \copy 混淆。\copy 调用 COPY FROM STDIN 或 COPY TO STDOUT,然后在 psql 客户端可访问的文件中获取/存储数据。因此,当使用 \copy 时,文件可访问性和访问权限取决于客户端而不是服务器。

您的应用程序编程语言可能也支持推送或获取数据,但您通常不能在标准 SQL 语句中使用COPY FROM STDIN/ TO STDOUT,因为无法连接输入/输出流。PHP的PostgreSQL的处理程序(PDO)包括非常基本的pg_copy_frompg_copy_to其复制到/从一个PHP数组,这可能不是高效的大数据集的功能。