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 的 delimited dollar quoting 和一个随机分隔符来帮助防止 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 元字符,而普通的<<__END__ 允许shell 解释它们。我们需要 shell 来解释元字符,因为我们需要将 sep 替换到此处的文档中,并且还需要使用 $(...)(相当于反引号)来插入文件文本。每次替换 seq 之前的 x 都存在,因为 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 注入攻击变得困难。
我还是建议你使用真正的脚本语言,但这说明确实是可以的。