[英]Read binary file with PostgreSQL without pg_read_file
我需要一个明确的 PostgreSQL 9.4 来解决以下问题:
编辑:
该文件位于集群路径之外,因此正常功能会引发:
SQL 错误:错误:不允许绝对路径
这是一个简单的 function get_file_contents(filename text) returns bytea
。
create or replace function get_file_contents(filename text) returns bytea as
$fn$
declare
lo_oid oid;
retval bytea;
begin
lo_oid := lo_import(filename);
retval := lo_get(lo_oid);
perform lo_unlink(lo_oid);
return retval;
end;
$fn$ language plpgsql;
-- Read the great work of Sun Tzu
select get_file_contents('/media/data/ForeignData/The Art Of War.pdf');
-- Insert into a table, update a table
insert into mytable (mycolumn[,<others>]) values (get_file_contents(myfilename)[,<others>]);
update mytable set mycolumn = get_file_contents(myfilename) where <whatever there>;
经过大量研究,我得出以下 function:
CREATE OR REPLACE FUNCTION file_read(file text)
RETURNS bytea AS $$
DECLARE
content text;
tmp text;
BEGIN
file := quote_literal(file);
tmp := quote_ident(md5(random()::text));
-- create tmp table using random name
EXECUTE 'CREATE TEMP TABLE ' || tmp || ' (id oid, file_name text, content bytea)';
-- add given filename
EXECUTE 'INSERT INTO '|| tmp ||' (file_name) VALUES('|| file ||')';
-- add the document to large object storage and return the link id
BEGIN
EXECUTE 'UPDATE ' || tmp || ' SET id = lo_import(file_name) ';
EXCEPTION WHEN OTHERS THEN
RETURN NULL;
END;
-- pull document from large object storage
EXECUTE 'UPDATE ' || tmp || ' SET content = lo_get(id) ';
-- delete the file from large object storage
EXECUTE 'SELECT lo_unlink(id) FROM ' || tmp;
-- save data to content variable
EXECUTE 'SELECT content FROM ' || tmp INTO content;
-- drop tmp table
EXECUTE 'DROP TABLE ' || tmp;
-- return
RETURN content;
END;
$$ LANGUAGE plpgsql VOLATILE;
示例用例:
从文件中读取select file_read(concat('/tmp/', '28528026bc302546d17ce7e82400ab7e.zip')
更新栏update custom_table set content = file_read(filename)
使用内置的 function pg_read_binary_file()
。 它从 Postgres 9.1 开始可用,并且完全符合您的要求。 手册:
返回文件的全部或部分。 这个 function 与
pg_read_file
相同,只是它可以读取任意二进制数据,返回结果为bytea
而不是text
; 因此,不执行编码检查。默认情况下,此 function 仅限于超级用户,但其他用户可以被授予
EXECUTE
以运行 function。
所以要...
将压缩文件从服务器读取到
bytea
列
UPDATE custom_table
SET content = pg_read_binary_file('/tmp/28528026bc302546d17ce7e82400ab7e.zip')
WHERE id = 123;
比任何解决方法都要快得多。
请注意此限制,引用手册:
只能访问数据库集群目录和 log_directory 中的文件。 对集群目录中的文件使用相对路径,并为日志文件使用与 log_directory 配置设置匹配的路径。
您可以使用从 db 目录到任何其他目录的符号链接来克服路径限制。 不过要警惕可能的安全隐患。 看:
此外,请考虑升级到 Postgres 的当前版本Postgres 9.4 已于 2020 年 2 月 13 日达到 EOL 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.