psql -d some_database -c \
"copy (select some_column from a_table where id=900) to stdout with BINARY;" > /tmp/tmp.gz
然后我想要做的是
gunzip /tmp/tmp.gz
有什么想法吗?
psql -d some_database -c \
"copy (select some_column from a_table where id=900) to stdout with BINARY;" > /tmp/tmp.gz
然后我想要做的是
gunzip /tmp/tmp.gz
一种可行的方法,虽然可能不太受欢迎:
psql -At -c "select encode(content, 'base64') from t where ..." | base64 -d
即,将内容打印为base64并解码。我认为实际情况是psql旨在产生可读输出,并且强制其排出原始二进制数据是有意困难的。
我想,如果你足够想要它,你可以编写一些工具(Perl / Python脚本)来连接到数据库并直接打印原始输出。
复制的“WITH BINARY”选项不仅执行简单的二进制输出,而且执行某些编码,这可能是不可靠的。
您确定把压缩后的文本以二进制形式存储在数据库中是最佳方式吗?根据文档,长文本会被系统自动压缩:
长字符串会被系统自动压缩,因此磁盘上物理需求可能更少。非常长的值也会存储在后台表中,以便它们不会干扰对较短列值的快速访问。无论如何,可以存储的最长字符字符串约为1 GB。
--no-align
和 --tuples-only
。gzip
。
psql --tuples-only --no-align -d some_database -c \
"copy (select some_column from a_table where id=900) to stdout with BINARY;" | gzip > /tmp/tmp.gz
我不知道有没有直接的方法... COPY 有一个可变长度头部的二进制格式,不太容易“修剪”。除此之外,PG 更偏向于文本,我认为没有办法强制从 BYTEA 字段的 SELECT 中输出“原始”(二进制)数据。
你可以获得文本十六进制输出,并编写一个小程序(C、Perl 或其他语言)将其从例如 \x000102414243
转换为二进制。这并不难,但也不是直接的方法(而且十六进制格式在 Postgresql 9.0 中)。
psql -t -q -c "select binaryfield from.. where ..." mydb | myhextobin > tmp.gz
顺便说一句,Grzegorz的回答非常恰当。
补充:并不是非常干净,也不是万无一失的,只是如果有人觉得有用的话...
/* expects a pg hexadecimal string, in "\x....." format, and converts to binary*/
/* warning: no checks! it just ignores chars outside [0-9a-f] */
#include<stdio.h>
int main() {
int x, pos, v;
char hex[3]={0,0,0};
pos = 0;
while( (x = getchar()) >= 0) {
if(( x >='0' && x <= '9') || ( x >= 'a' && x <= 'f' )) {
hex[pos++] = (char)x;
if(pos == 2) {
sscanf(hex, "%x", &v);
putchar((char)v);
pos = 0;
}
}
}
return pos==0 ? 0 : 1;
}
不建议尝试解码PostgreSQL二进制格式。仅仅因为您正在使用的测试文件有效,并不意味着一切都能正常工作。例如,某些字符序列(未出现在您的测试文件中)可能会被转义。
b
是一个bytea
字段(这是我的假设),那么这些输出的应该是十六进制字符串,而不是原始二进制内容。(我没有点踩) - leonbloy你可以使用具有客户端驱动程序和读取bytea类型的能力的编程语言来更轻松地完成此操作:PHP、Python、Ruby、Perl、JavaScript、Java等。只需在其中执行查询,使用可能已经存在于该语言中的gzip库,并将文件写出。
或者,你可以在数据库内部使用过程化语言并创建存储过程。你需要将所请求的文件名传递给存储过程。
encode()
和base64类型。 - justis