psql
除非您打算将其存储为大对象,否则无法直接为您读取文件,在这种情况下您可以使用lo_import
. 见psql
命令\lo_import
。
更新:@AlexandreAlves 指出,您实际上可以在使用时啜饮文件内容
\set myvar = `cat somefile`
然后将其作为psql
变量引用:'myvar'
。便利。
虽然可以使用 shell 读取文件并将其提供给它,psql
但充其量是很尴尬的,因为 shell 既不提供具有参数化查询支持的本机 PostgreSQL 数据库驱动程序,也不提供任何文本转义功能。您必须滚动自己的字符串转义。
即使这样,您也需要知道输入文件的文本编码对您有效,client_encoding
否则您将插入垃圾和/或出错。通过与 PostgreSQL (如 Python、Perl、Ruby 或 Java)的适当集成,它很快就会变得更容易用一种语言来完成。
但是,如果你真的必须的话,有一种方法可以在 bash 中做你想做的事情:使用 Pg 的分隔美元引号和随机分隔符来帮助防止 SQL 注入攻击。它并不完美,但非常接近。我现在正在写一个例子。
鉴于有问题的文件:
$ cat > difficult.txt <__END__
Shell metacharacters like: $!(){}*?"'
SQL-significant characters like "'()
__END__
和样品表:
psql -c 'CREATE TABLE testfile(filecontent text not null);'
你可以:
#!/bin/bash
filetoread=$1
sep=$(printf '%04x%04x\n' $RANDOM $RANDOM)
psql <<__END__
INSERT INTO testfile(filecontent) VALUES (
\$x${sep}\$$(cat ${filetoread})\$x${sep}\$
);
__END__
这可能有点难以阅读,并且随机字符串生成是特定于 bash 的,尽管我确信可能有可移植的方法。
生成一个由字母数字字符组成的随机标签字符串(为方便起见,我使用了十六进制)并存储在seq
.
psql
然后使用未引用的 here-document 标记调用。缺少引号很重要,因为它<<'__END__'
会告诉bash
不要解释字符串中的 shell 元字符,而 plain<<__END__
允许 shell 解释它们。我们需要 shell 来解释元字符,因为我们需要替换sep
到 here 文档中,并且还需要使用$(...)
(相当于反引号)来插入文件文本。x
每次替换之前都存在,seq
因为 here-document 标记必须是有效的 PostgreSQL 标识符,因此它们必须以字母而不是数字开头。每个标签的开头和结尾都有一个转义的美元符号,因为 PostgreSQL 美元引号的形式是$taghere$quoted text$taghere$
.
因此,当脚本被调用时,bash testscript.sh difficult.txt
此处的文档会扩展为以下内容:
INSERT INTO testfile(filecontent) VALUES (
$x0a305c82$Shell metacharacters like: $!(){}*?"'
SQL-significant characters like "'()$x0a305c82$
);
其中标签每次都不同,这使得依赖于过早结束引用的 SQL 注入漏洞变得困难。
我仍然建议您使用真正的脚本语言,但这表明它确实是可能的。