- 文档
- 教程
- 知识库
【免费下载链接】til
:memo: Today I Learned
在 psql 交互式会话中,绝大多数查询语句都以分号;结尾来提交执行。其实 psql 还提供了一种更灵活的替代写法:以\g元命令作为语句终止符,它同样会把 SQL 发送给 PostgreSQL 服务器执行,并且支持把查询结果直接落盘到指定文件,而不是打印到终端。本文基于 til 仓库的 write-a-query-result-to-file.md 整理,完整讲解\g的两种用法、与分号提交方式的区别,并结合仓库内 psql 相关文档给出导出 CSV、配合EXPLAIN等实战组合,读完即可在真实会话中把任何查询结果持久化到文件。
分号之外的另一种语句终止符:\g
psql 是一个交互式命令行工具,它把用户输入的 SQL 语句累积到内部缓冲区(query buffer)中,直到遇到语句终止符才一次性发送给 PostgreSQL 服务器执行。最常见的终止符是分号;,但 psql 同样认可\g元命令:
select 1 \g上面这条语句会正常执行,输出如下(开启\timing时会附带执行耗时):
?column? ---------- 1 (1 row)\g与分号的区别在于:分号只是“结束并发送”这一件事,而\g在完成同样的发送动作之外,还额外支持“把结果重定向到文件”。如果\g后面不带任何参数,它的行为与分号完全一致——结果照常输出到会话中;一旦在后面跟上一个文件名,结果就会被写入该文件。这意味着你可以在一个命令里同时完成“执行查询”和“保存结果”两件事,而无需先执行、再通过其他工具截取输出。
这一特性尤其适合以下场景:
- 想把某条临时查询的结果留档,供后续查看或交给同事;
- 想将查询结果作为其他脚本的输入,让输出走文件而不是终端;
- 查询结果较多时,避免刷屏(关于输出较长时 psql 的分页行为,可参考 toggling-the-pager-in-psql.md 中的
\pset pager off说明)。
把查询结果写入文件:\g filename
在\g后面直接写上文件名,查询结果就会被写入该文件:
> select 1, 2, 3 \g query_result.txt执行后终端不会打印查询结果本身(从上面的输出可以看出没有出现数据行),结果被写入当前工作目录下的query_result.txt。随后可以在 psql 内部用\!转义命令调用 shell 的cat来查看文件内容:
> \! cat query_result.txt ?column? | ?column? | ?column? ----------+----------+---------- 1 | 2 | 3 (1 row)\!是 psql 的 shell 转义元命令,它把后续的命令字符串交给操作系统的 shell 执行,因此在会话里就能直接cat、less或wc -l检查刚生成的文件,无需退出 psql。上面示例中的Time: 4.293 ms属于会话的\timing输出,它仍打印在终端上,并不会被写进query_result.txt。
\g 与 \o、COPY 等文件输出方案的对比
psql 中把查询输出导向文件并非只有\g一条路,理解它们的差异有助于按需选择:
| 方式 | 语法 | 特点 |
|---|---|---|
\g filename | select ... \g filename | 单条语句执行后将结果写入文件,与会话输出格式一致(含列名、分隔线、行数统计等人类可读排版) |
\o filename | \o filename后再执行语句 | 会话级输出重定向开关,后续所有查询结果都持续写入同一文件,直到\o恢复终端输出 |
COPY ... TO | copy (select ...) to '/path/file.csv' csv; | 由服务器端执行,输出纯数据(可指定 CSV 格式),对权限有要求,详见仓库文档 export-query-results-to-a-csv.md |
\copy | \copy (select ...) to '/path/file.csv' with csv header; | 客户端侧执行的 COPY,权限要求更低,适合普通用户 |
其中\g filename写入的是 psql 默认的排版输出(如上例中的?column?列头与(1 row)统计),适合快速留档、肉眼阅读;而需要机器可读的 CSV 数据时,应优先使用 export-query-results-to-a-csv.md 介绍的COPY/\copy:
copy (select * from pokemons) to '/tmp/pokemon_dump.csv' csv header;进阶组合:保存 EXPLAIN 计划、脚本化落盘
\g filename对任意返回结果的语句都生效,因此也可以配合EXPLAIN使用,把查询计划保存下来反复研究。仓库文档 output-explain-query-plan-in-different-formats.md 展示了EXPLAIN (ANALYZE, FORMAT JSON)这样的多格式输出;若再叠加\g,即可将计划直接存入文件:
> explain (analyze, format json) select title from books where created_at > now() - '1 year'::interval \g plan.json另一种常见做法是把\g与-f结合:先在编辑器(如 Vim)里把完整的SELECT ... \g /tmp/result.txt写成.sql文件,再通过psql -f query.sql批量执行,即可实现脚本化查询落盘;仓库文档 print-the-query-buffer-in-psql.md 中提到的\p元命令也能帮你确认缓冲区中正在编辑的语句内容,减少多行粘贴时的出错概率。
小结
- 以
\g结束一条 SQL,与分号等价地将其发送给服务器执行; \g filename在发送语句的同时,把查询结果以 psql 排版格式写入指定文件;- 会话内可用
\! cat filename直接核对文件内容; - 需要纯数据或 CSV 时,改用
COPY/\copy;需要持续重定向时,使用\o; - 更多细节可查阅
man psql,或阅读仓库内 write-a-query-result-to-file.md 原文。
- 文档
- 教程
- 知识库
【免费下载链接】til
:memo: Today I Learned
相关推荐
SeaweedFS PostgreSQL 协议接入实战:用 psql、JDBC、psycopg2 与 BI 工具直接查询 MQ 数据
SeaweedFS PostgreSQL 协议接入实战:用 psql、JDBC、psycopg2 与 BI 工具直接查询 MQ 数据 本篇指南基于 postgr
分布式文件系统对象存储存储如何用 lz4 --sparse 把解压结果写入稀疏文件?
如何用 lz4 sparse 把解压结果写入稀疏文件? 当 .lz4 压缩包里含有大段连续零字节的数据(例如磁盘镜像、备份数据)时,直接解压会让输出文件按名义大
存储系统编程beets limit 插件详解:用 lslimit 命令与 `<n` 查询前缀截取查询结果
beets limit 插件详解:用 lslimit 命令与 <n 查询前缀截取查询结果 beets 的 limit 插件用于把一次查询的结果截断为"前 N 条
音频CLI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考