要将bytea保存到磁盘服务器端,必须是数据库超级用户。不允许普通用户写入文件系统。
假设具有超级用户权限,最简单的方法是将其实现为“不受信任”语言之一的功能。
CREATE FUNCTION bytea_to_file(bytea,text) RETURNS void AS $$
open(my $fd, ">".$_[1]) or die $!;
binmode($fd);
print $fd decode_bytea($_[0]);
close($fd);
$$ language plperlu;
Run Code Online (Sandbox Code Playgroud)
用法:
select bytea_to_file(bytea_column, concat('/path/to/destination/', id_column))
from tablename where...
Run Code Online (Sandbox Code Playgroud)
如果此类语言在您的 postgres 环境中不可用,则可以在 pl/pgsql 中制作一个非高效版本。这是低效的,因为它必须创建一个临时大对象并将整个数据复制到其中,然后再将其导出为文件,然后清除大对象。
CREATE FUNCTION bytea_to_file_with_lo(bytea,text) RETURNS void AS $$
declare
o oid;
fd integer;
INV_WRITE int := 131072;
begin
o:=lo_create(-1);
fd:=lo_open(o, INV_WRITE);
if (fd<0) then
raise exception 'Failed to open large object %', o;
end if;
perform lowrite(fd, $1);
if (lo_close(fd)<>0) then
raise exception 'Failed to close large object %', o;
end if;
perform lo_export(o, $2);
perform lo_unlink(o);
end;
$$ language plpgsql;
Run Code Online (Sandbox Code Playgroud)
用法:与 pl/perlu 版本相同。您仍然需要成为超级用户,除非此功能的超级用户权限仅授予其他用户(在当前情况下,只有100% 信任用户才可以,否则将是灾难性的):
alter FUNCTION bytea_to_file_with_lo(bytea,text) SECURITY DEFINER;
Run Code Online (Sandbox Code Playgroud)
当您拥有的只是客户端psql解释器时,无法直接提取二进制内容(归结为 psql 对 '\0' 字节不利),但可以轻松获得十六进制或 base64 的中间表示并在 psql 之外进行后处理。
shell 中的示例,假设存在base64来自 GNU coreutils的命令:
$ psql -Atc "select encode(bytea_column,'base64') from tablename" | \
base64 -d >/path/to/destination/filename
Run Code Online (Sandbox Code Playgroud)
这一次只输出一行和一列。同时提取另一列(如 ID)对于后处理来说将明显困难得多,因此这个简单的示例假设某种外部循环遍历先前已获得的 ID。
| 归档时间: |
|
| 查看次数: |
2676 次 |
| 最近记录: |