我一直在搜索,但到目前为止我只发现了如何根据csv文件在表中插入日期。
我有以下情况:
目录名= ticketID
在这个目录里面我有几个文件,比如:
Description.txt
Summary.txt
- 包含故障单标题并已成功导入。Progress_#.txt
- 这是每次门票被udpdated时。我收到了一个新文件。Solution.txt
导入Issue.txt
非常简单,因为这实际上是一个CSV。
现在问题在于描述和进度文件。
我需要使用此文件中的数据更新现有行。
上的东西update table_ticket set table_ticket.description = Description.txt where ticket_number = directoryname
我正在使用PostgreSQL,COPY
命令对新数据有效,但由于',; /特殊字符,它仍然会失败。
我想使用bash脚本执行此操作,但似乎不可能:
for i in `find . -type d`
do
update table_ticket
set table_ticket.description = $i/Description.txt
where ticket_number = $i
done
当然上面的代码会考虑与数据库的连接。
任何人都知道如何使用shell脚本实现这一目标。或者用Java创建一些东西并阅读和更新记录会更好,尽管我想避免这种方法。
由于 亚历
答案 0 :(得分:4)
感谢您的回答,但我遇到了这个问题:
psql -U dbuser -h dbhost db
\set content = `cat PATH/Description.txt`
update table_ticket set description = :'content' where ticketnr = TICKETNR;
将其放入一个简单的脚本中我创建了以下内容:
#!/bin/bash
for i in `find . -type d|grep ^./CS`
do
p=`echo $i|cut -b3-12 -`
echo $p
sed s/PATH/${p}/g cmd.sql > cmd.tmp.sql
ticketnr=`echo $p|cut -b5-10 -`
sed -i s/TICKETNR/${ticketnr}/g cmd.tmp.sql
cat cmd.tmp.sql
psql -U supportAdmin -h localhost supportdb -f cmd.tmp.sql
done
缺点是它将始终创建一个新连接,稍后我将更改为创建单个文件
但它完全符合我的要求,将内容放在一个列中。
答案 1 :(得分:2)
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
。缺少引用很重要,因为<<'__END__'
会告诉bash
不要解释字符串中的shell元字符,而普通<<__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注入漏洞依赖于过早结束引用的难度。
我仍然建议您使用真正的脚本语言,但这表明它确实可行。
答案 2 :(得分:0)
最好的办法是创建一个临时表,从相关文件中复制那些表,然后运行更新。
你的第二个选择是用pl / perlu这样的语言创建一个函数,并在存储过程中执行此操作,但是当你从临时表更新时,你将失去很多性能优化。