postgresql - 如何用SQL导出全文文件?

标签 postgresql export

将全文字段导入/导出为文件的简单方法吗?

  • 解决了“作为多行加载”的问题。
    尝试使用 SQL 的 COPY我只能将全文件转换为全表,而不是单个文本字段,因为 COPY 中的每一行都是原始的。

  • 解决回存问题,将完整的 XML 文件保存在文件系统中,不改变二进制表示(保留 SHA1),并且不使用其他外部过程(如 Unix sed 使用)。

主要问题出在导出,所以这是本页的标题。

PS:往返过程中的“同文件证明”——导入、导出返回并与原文件比较——可以通过sha1sum演示获得;请参阅下面的示例。所以,一个很自然的需求也是通过SQL来校验同一个SHA1,避免在简单的校验任务上导出。


所有例子

  1. 将全文导入到全表(这不是我需要的),
    并测试是否可以导出为相同的文本.
    PS:我需要将一个文件导入一个字段一行。

  2. 完整表格转换为一个文件(这不是我需要的)
    并测试是否可以导出为相同文本。
    PS:我需要一行(一个字段)到一个文件中。

  3. 通过SQL计算哈希,字段的SHA1
    比较时必须相同 ...否则这对我来说不是解决方案。

以下示例显示了每个问题和非优雅的解决方法。

<强>1。导入

CREATE TABLE ttmp (x text);
COPY ttmp FROM '/tmp/test.xml' ( FORMAT text ); -- breaking lines lines
COPY (SELECT x FROM ttmp) TO '/tmp/test_back.xml' (format TEXT);

检查 original 和“back”是否有完全相同的内容:

sha1sum /tmp/test*.*
  570b13fb01d38e04ebf7ac1f73dfad0e1d02b027  /tmp/test_back.xml
  570b13fb01d38e04ebf7ac1f73dfad0e1d02b027  /tmp/test.xml

PS:看起来很完美,但这里的问题是使用了很多行。真正的导入解决方案可以将文件导入一行(和一个字段)。真正的导出解决方案是一个 SQL 函数,它从单行(单字段)生成 test_back.xml

<强>2。将全表转换为一个文件

用它来存储 XML:

CREATE TABLE xtmp (x xml);
INSERT INTO  xtmp (x) 
  SELECT array_to_string(array_agg(x),E'\n')::xml FROM ttmp
;
COPY (select x::text from xtmp) TO '/tmp/test_back2-bad.xml' ( FORMAT text );

... 但无法正常工作,因为我们可以通过 sha1sum/tmp/test*.xml 检查,对于 test_back2-bad,不会产生相同的结果。 xml.

也可以使用外部工具(perl、sed 或任何其他工具)将 \n 转换为 chr(10)
perl -p -e 's/\\n/\n/g'/tmp/test_back2-bad.xml >/tmp/test_back2-good.xml

好的,现在 test_back2-good.xml 与原始哈希值相同(在我的示例中为“570b13fb...”)。 使用 Perl 是一种解决方法,没有它怎么办?

<强>3。字段的SHA1

SELECT encode(digest(x::text::bytea, 'sha1'), 'hex') FROM xtmp;

未解决,与原始哈希不同(在我的示例中为“570b13fb...”)...也许 ::text 强制使用 \n< 进行内部表示 符号,因此解决方案将直接转换为 bytea,但它是无效转换。其他解决方法也不是解决方案,

SELECT encode(digest( replace(x::text,'\n',E'\n')::bytea, 'sha1' ), 'hex') 
FROM xtmp

...我尝试使用CREATE TABLE btmp (x bytea)COPY btmp FROM '/tmp/test.xml' (FORMAT binary),但出现错误("未知的 COPY 文件签名”)。

最佳答案

COPY不是为此而设计的。它是用来处理表结构的数据的,所以如果没有一些划分行和列的方法,它就无法工作;总会有一些字符 COPY FROM解释为分隔符,并且 COPY TO如果它在您的数据中找到一个转义序列,它将插入一些转义序列。如果您正在寻找通用文件 I/O 工具,这不是很好。

事实上,数据库服务器并不是为一般的文件 I/O 而设计的。一方面,任何 直接与服务器文件系统交互的东西都需要 super 用户角色。如果可能的话,您应该像往常一样查询表,并在客户端处理文件 I/O。

也就是说,有几种选择:

  • 内置 pg_read_file() 功能,和 pg_file_write() 来自 adminpack模块,为文件系统提供最直接的接口(interface),但它们都被限制在集群的数据目录中(我不建议在其中存储随机的用户创建的文件)。
  • lo_import() and lo_export() 是我所知道的唯一内置函数,它们直接处理文件 I/O 并且可以不受限制地访问服务器的文件系统(在主机操作系统强加的限制内),但是大对象接口(interface)不是特别用户友好....
  • 如果您安装了 Perl ( plperlu ) 或 Python ( plpythonu ) 等过程语言的不受信任变体,您可以为该语言的 native I/O 例程编写包装函数。
  • 通过 COPY TO PROGRAM 没有什么是您无法完成的如果你有足够的决心 - 对于一个人,你可以 COPY (SELECT 1) TO PROGRAM 'mv <source_file> <target_file>'解决 pg_file_write() 的限制- 尽管这在某种程度上模糊了 SQL 和外部工具之间的界限(并且继承您的代码库的人可能不会留下深刻印象...)。

关于postgresql - 如何用SQL导出全文文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48327289/

相关文章:

postgresql - 执行 COPY..TO 语句时无法确定参数 $1 的数据类型

vba - 将 Excel 工作表(部分)的范围导出到 CSV

c# - 将 Pervasive 导出到 MySQL (C#)

linker - C++ 中的符号 – 它们是否在非调试版本中导出?

hibernate - 无法将 Postgres 与 hibernate 连接

sql - PostgreSQL 更新不返回零计数

python - 使用 psycopg2 将 PostgreSQL UUID 数组作为列表返回

perl - 在 Ubuntu 中的 postgres-9.4 上安装 perl 扩展时出错

ios - 将屏幕截图创建的 gif 文件保存到相机胶卷

java - JFreeChart - 将图表转换为 PDF,每页一个