回答你的实际问题
是的。您可以使用命名管道而不是创建文件。考虑以下演示。
x
在我的数据库中创建一个模式event
进行测试:
-- DROP SCHEMA x CASCADE;
CREATE SCHEMA x;
CREATE TABLE x.x (id int, a text);
从 shell 创建一个命名管道(fifo),如下所示:
postgres@db:~$ mkfifo --mode=0666 /tmp/myPipe
1 )使用服务器上的COPY
命名管道调用 SQL 命令:
postgres@db:~$ psql event -p5433 -c "COPY x.x FROM '/tmp/myPipe'"
这将获得数据库中表的排他锁。x.x
连接保持打开状态,直到 fifo 获取数据。小心不要让这个打开太久!您可以在填充管道后调用它以最大限度地减少阻塞时间。您可以选择事件的顺序。该命令在两个进程绑定到管道后立即执行。第一个等待第二个。
或者2)您可以从客户端上的管道执行 SQL :
postgres@db:~$ psql event -p5433 -f /tmp/myPipe
这更适合您的情况。此外,在 SQL 被一次性执行之前不会锁定表。
Bash 会出现阻塞。它正在等待输入到管道。要从一个 bash 实例完成所有操作,您可以将等待进程发送到后台。像这样:
postgres@db:~$ psql event -p5433 -f /tmp/myPipe 2>&1 &
无论哪种方式,从同一个 bash 或不同的实例,您现在都可以填充管道。变体1)
的三行演示:
postgres@db:~$ echo '1 foo' >> /tmp/myPipe; echo '2 bar' >> /tmp/myPipe; echo '3 baz' >> /tmp/myPipe;
(注意使用制表符作为分隔符或使用COPY指示接受不同的分隔符WITH DELIMITER 'delimiter_character'
)
这将使用 COPY 命令触发挂起的 psql 执行并返回:
COPY 3
变体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
完成后删除命名管道:
postgres@db:~$ rm /tmp/myPipe
检查成功:
event=# select * from x.x;
id | a
----+-------------------
1 | foo
2 | bar
3 | baz
上面代码的有用链接
使用命名管道使用 postgres 读取压缩文件 命名管道
简介
在后台运行 bash 脚本的最佳实践
您可能需要或不需要的建议
对于批量,您有比每行INSERT
单独插入更好的解决方案。使用此语法变体:
INSERT INTO mytable (col1, col2, col3) VALUES
(1, 'foo', 'bar')
,(2, 'goo', 'gar')
,(3, 'hoo', 'har')
...
;
将您的陈述写入文件并INSERT
像这样做一个质量:
psql -h remote_server -U username -d database -p 5432 -f my_insert_file.sql
(5432 或 db-cluster 正在侦听的任何端口)
my_insert_file.sql
可以容纳多个 SQL 语句。事实上,像这样恢复/部署整个数据库是很常见的做法。请查阅有关参数的手册-f
,或在 bash:中查阅man psql
。
或者,如果您可以将(压缩)文件传输到服务器,则可以使用COPY更快地插入(解压缩)数据。
您还可以在 PostgreSQL 中进行部分或全部处理。为此,您可以COPY TO
(或INSERT INTO
)一个临时表并使用普通 SQL 语句来准备并最终插入/更新您的表。我经常这样做。请注意,临时表在会话中生死攸关。
您可以使用像pgAdmin这样的 GUI来进行舒适的处理。SQL 编辑器窗口中的会话保持打开状态,直到您关闭该窗口。(因此,临时表会一直存在,直到您关闭窗口。)