aza*_*a07 12 database postgresql connection shell psql
我有大量的数据文件要处理并存储在远程数据库中.数据文件的每一行代表数据库中的一行,但必须在插入数据库之前进行格式化.
我的第一个解决方案是通过编写bash脚本并生成SQL数据文件来处理数据文件,然后将转储SQL文件导入数据库.这个解决方案似乎太慢,你可以看到涉及创建中间SQL文件的额外步骤.
我的第二个解决方案是编写bash脚本,在处理数据文件的每一行时,创建和INSERT INTO ...声明并将SQL语句发送到远程数据库:
echo sql_statement | psql -h remote_server -U username -d database
即不创建SQL文件.但是,这个解决方案有一个主要问题,我正在寻求建议:
每次我必须重新连接到远程数据库以插入一行.
有没有办法连接到远程数据库,保持连接,然后"管道"或"发送"插入SQL语句而不创建一个巨大的SQL文件?
Erw*_*ter 19
是的.您可以使用命名管道而不是创建文件.请考虑以下演示.
x在我的数据库中创建架构以event进行测试:
-- DROP SCHEMA x CASCADE;
CREATE SCHEMA x;
CREATE TABLE x.x (id int, a text);
Run Code Online (Sandbox Code Playgroud)
从shell创建一个命名管道(fifo),如下所示:
postgres@db:~$ mkfifo --mode=0666 /tmp/myPipe
Run Code Online (Sandbox Code Playgroud)
无论是1)调用SQL命令COPY使用命名管道在服务器上:
postgres@db:~$ psql event -p5433 -c "COPY x.x FROM '/tmp/myPipe'"
Run Code Online (Sandbox Code Playgroud)
这将获取数据库中表的独占锁x.x.连接保持打开状态,直到fifo获取数据.小心不要让它打开太久!填充管道后可以调用此方法以最大限度地缩短阻塞时间.您可以选择事件序列.只要两个进程绑定到管道,该命令就会执行.第一个等待第二个.
或者2)您可以从客户端上的管道执行SQL :
postgres@db:~$ psql event -p5433 -f /tmp/myPipe
Run Code Online (Sandbox Code Playgroud)
这更适合您的情况.此外,在SQL以单件执行之前,没有表锁定.
Bash会出现阻止.它正在等待输入管道.要从一个bash实例执行所有操作,您可以将等待进程发送到后台.像这样:
postgres@db:~$ psql event -p5433 -f /tmp/myPipe 2>&1 &
Run Code Online (Sandbox Code Playgroud)
无论哪种方式,从相同的bash或不同的实例,您现在可以填充管道.
变体1)的三行演示:
postgres@db:~$ echo '1 foo' >> /tmp/myPipe; echo '2 bar' >> /tmp/myPipe; echo '3 baz' >> /tmp/myPipe;
Run Code Online (Sandbox Code Playgroud)
(注意使用制表符作为分隔符或指示COPY接受使用不同的分隔符WITH DELIMITER 'delimiter_character')
这将触发挂起的psql,并使用COPY命令执行并返回:
COPY 3
Run Code Online (Sandbox Code Playgroud)
变体2)的演示:
postgres@db:~$ (echo -n "INSERT INTO x.x VALUES (1,'foo')" >> /tmp/myPipe; echo -n ",(2,'bar')" >> /tmp/myPipe; echo ",(3,'baz')" >> /tmp/myPipe;)
INSERT 0 3
Run Code Online (Sandbox Code Playgroud)
完成后删除命名管道:
postgres@db:~$ rm /tmp/myPipe
Run Code Online (Sandbox Code Playgroud)
检查成功:
event=# select * from x.x;
id | a
----+-------------------
1 | foo
2 | bar
3 | baz
Run Code Online (Sandbox Code Playgroud)
使用命名管道使用postgres读取压缩文件命名管道
简介
在后台运行bash脚本的最佳实践
对于批量,INSERT您有比每行单独的INSERT更好的解决方案.使用此语法变体:
INSERT INTO mytable (col1, col2, col3) VALUES
(1, 'foo', 'bar')
,(2, 'goo', 'gar')
,(3, 'hoo', 'har')
...
;
Run Code Online (Sandbox Code Playgroud)
将您的语句写入文件并执行INSERT如下操作:
psql -h remote_server -U username -d database -p 5432 -f my_insert_file.sql
Run Code Online (Sandbox Code Playgroud)
(5432或db-cluster正在侦听的任何端口)
my_insert_file.sql可以包含多个SQL语句.事实上,恢复/部署这样的整个数据库是常见的做法.有关参数的信息,请参阅手册-f,或者参考bash : man psql.
或者,如果您可以将(压缩的)文件传输到服务器,则可以使用COPY更快地插入(解压缩的)数据.
您也可以在PostgreSQL中进行部分或全部处理.为此,您可以COPY TO(或INSERT INTO)使用临时表并使用纯SQL语句来准备并最终INSERT/UPDATE您的表.我做了很多.请注意临时表会在会话中生存并消亡.
您可以使用像pgAdmin这样的GUI 来实现舒适的处理.在关闭窗口之前,SQL编辑器窗口中的会话将保持打开状态.(因此,临时表会一直存在,直到您关闭窗口.)