TextQL 介绍与选型指南
TextQL 是 dinedal 开发的 Go 单二进制工具,把 CSV/TSV 等分隔符文本直接载入 SQLite 内存库执行 SQL,本文实测 2.0.3(master 源码构建)的安装与查询能力,如实呈现其 2015 年后停更状态,并与 csvq/dsq/trdsql/OctoSQL/SQLite 做量化选型对比
TextQL 介绍与选型指南
目标:回答"TextQL 是什么、能干什么、今天还值不值得选"——在 Ubuntu 22.04 服务器上实测 2.0.3(master 源码构建)的安装与查询能力,用可核验的社区指标说明其维护现状,并与 csvq、dsq、trdsql、OctoSQL、sqlite3 原生
.import做量化对比,给出选型结论。以下所有命令与输出均已在 Ubuntu 22.04(x86_64)+ TextQL 2.0.3 环境实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(jammy),内核 7.0.0-38-generic,架构 x86_64
- TextQL 版本:2.0.3(
VERSION文件值;二进制由 master 分支最后提交e6545d5(2023-10-22)源码构建,并以-ldflags "-X main.VERSION=2.0.3 -s"注入版本串,故含 2015 年 release 没有的-sqlfile参数) - 安装方式:源码构建后
install到/usr/local/bin/textql,产物 4,408,672 字节(4.3 MB)单二进制,ldd实测仅动态链接libc.so.6,无其他运行时依赖 - 构建工具链:go 1.18.1、gcc 11.4.0(
mattn/go-sqlite3走 CGO,编译器必需)、git 2.34.1;sqlite33.37.2 仅在用-console时需要 - 验证回显:
$ textql -version
2.0.3
$ ls -la /usr/local/bin/textql
-rwxr-xr-x 1 root root 4408672 Nov 3 04:36 /usr/local/bin/textql
$ du -h /usr/local/bin/textql
4.3M /usr/local/bin/textql
- 测试数据:
/root/textql-lab目录下的sales.csv(10 行销售流水)、regions.csv(3 行维表)、nginx.tsv、semi.csv、nohdr.csv、query.sql与multi/子目录(内容见第五章快速开始)
二、软件概述
TextQL 是 dinedal/textql 项目(作者 Paul Bergeron,GitHub 描述 "Allows you to easily execute SQL against structured text like CSV or TSV")提供的命令行工具,定位是:不装数据库、不写导入脚本,把 CSV/TSV/任意分隔符文本一次性载入 SQLite 内存库,直接跑标准 SQLite 方言的 SQL。与"文件即表、可回写源文件"的 csvq 路线不同,TextQL 是"导入-查询-丢弃"的一次性模型:所有 INSERT/UPDATE 只作用于内存库,除非 -save-to 显式落盘,否则进程退出即消失,源文件永不改动。
官方 README 把它与 sqlite3 原生导入的差异概括为三点(实测均成立):sqlite3 .import 不接受 stdin、TextQL 接受;sqlite3 不支持引号包裹的分隔符、TextQL 支持;TextQL 尽量吃内存库、只在要求时才触磁盘。
维护状态(查询日期 2026-11-03,取自 GitHub 仓库页与 releases Atom):
| 指标 | 值 |
|---|---|
| 仓库创建 | 2014-02-03 |
| Stars / Watchers | 9,093 / 155 |
| 许可证 | MIT |
| 最新 release | 2.0.3,发布于 2015-12-17,且只提供 Source code 资产、无任何 Linux 二进制 |
| master 最后提交 | 2023-10-22(PR #141 增加 -sqlfile) |
也就是说:功能面 2015 年后基本冻结,但社区关注度极高(9k+ star),仓库未归档。选型时必须把"无预编译包、必须自行构建、bug 无人修复"计入成本,详见第七章。
💡 技术拓展:README 末尾自嘲式 FAQ——"Is it any good? Yes",这条 Hacker News 老帖正是其 star 数远超功能复杂度的由来:它是最早把"CSV 即席 SQL"做成单二进制的工具之一。
三、核心架构
TextQL 代码分 5 个包(inputs/outputs/storage/sqlparser/util),主流程在 textql/main.go,全程单进程、无外部服务:
- 输入层(inputs.CSVInput):按
-dlm指定的分隔符与-header开关逐行解析文件;表名自动取文件名基名(sales.csv→sales),可用名字:文件语法覆写;目录参数非递归展开为其中每个文件;stdin 有管道数据时自动作为一个输入表载入。 - 存储层(storage):基于
mattn/go-sqlite3创建内存 SQLite 库,每个输入文件建一张表;所有列一律建为NUMERIC类型,由 SQLite 亲和性对每个值动态推断(实测typeof()同列可返回real/text/integer)。若系统存在可选的libgo-sqlite3-extension-functions.so,启动时自动加载(stdev/median 等聚合扩展)。 - SQL 层:
-sql/-sqlfile的语句按分号拆分后原样交给 SQLite 执行——TextQL 没有自研引擎,因此完整 SQLite 方言可用(strftime、窗口函数、CTE、JOIN等),这是它与同类工具最大的能力差异。 - 输出层(outputs):
CSVOutput(按-output-dlm分隔)与PrettyCSVOutput(-pretty,tablewriter 框线表)两种,写 stdout 或-output-file。 - REPL(-console):
exec.LookPath("sqlite3")找到系统 sqlite3 后 fork 之,把数据(临时库或-save-to库)交给官方 REPL。
$ cat /work/textql-src/go.mod
module github.com/dinedal/textql
go 1.13
require (
github.com/mattn/go-runewidth v0.0.2 // indirect
github.com/mattn/go-sqlite3 v2.0.3+incompatible
github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84
)
四、功能特性
以下特性全部在 Ubuntu 22.04 + TextQL 2.0.3 实测确认:
| 特性 | 实测结论 |
|---|---|
| 文件名即表名 | sales.csv → SELECT * FROM sales,无需导入语句 |
| stdin 管道输入 | 管道表名为 stdin(README 示例写的 pipe 是错的,实测报 no such table: pipe) |
| 表名覆写 | "orders:sales.csv" 语法可指定表名;非法字符拒绝:Invalid table name bad[]name |
| 目录批量载入 | 目录参数非递归,每个文件各成一张表(multi/ 下 t1.csv、t2.csv → 表 t1、t2) |
| 多文件 JOIN | 命令行并列多个文件即可跨表 JOIN |
| 短 SQL 语法 | 单表时可省略 FROM 表名,简单查询可省略 SELECT:-sql "*"、-sql "count(*)" |
| 类型推断 | 所有列建为 NUMERIC,typeof(amount)→real、typeof(date)→text、typeof(id)→integer |
| 日期函数 | strftime('%Y-%m', date) 对文本日期列直接生效 |
| 内置 regexp | WHERE product regexp 'Widget[AB]' 开箱可用 |
| 输出控制 | -output-header 列名、-output-dlm 输出分隔符、-pretty 框线表、-output-file 落盘 |
| 持久化 | -save-to x.sqlite 留下标准 SQLite 库,sqlite3 可续查续用 |
| REPL | -console fork 系统 sqlite3 打开数据(需 PATH 有 sqlite3,拒绝管道输入) |
| SQL 文件 | -sqlfile 从文件读语句(2023-10 加入 master;2015 的 2.0.3 release 源码没有) |
| 多语句 | 分号拆分顺序执行;引号内分号有专门合并处理(handleSemiColon) |
| 扩展函数库 | 安装 go-sqlite3-extension-functions 后自动加载 stdev/median/mode 等(本文未装该库,清单照抄 README) |
五、快速开始
以下五步在 Ubuntu 22.04 服务器上从零跑通,命令与输出均为实测。
5.1 安装二进制
TextQL 的 GitHub release 不提供预编译二进制;Ubuntu 22.04 最省事的是 apt(universe 包 2.0.3-4build1,但基于 2015 年源码、无 -sqlfile),生产主线建议源码构建(两条途径的完整流程与排障见《Ubuntu 22.04 安装 TextQL 2.0.3 指南》第四、六章)。构建产物验证:
$ install -m 755 build/textql /usr/local/bin/textql
$ textql -version
2.0.3
5.2 准备测试数据
$ mkdir -p /root/textql-lab && cd /root/textql-lab
$ cat > sales.csv <<'EOF'
id,date,region,product,amount,qty
1,2026-01-03,east,WidgetA,120.50,3
2,2026-01-04,east,WidgetB,89.90,1
3,2026-01-05,west,WidgetA,210.00,5
4,2026-02-01,north,WidgetC,55.25,2
5,2026-02-07,west,WidgetB,310.75,7
6,2026-02-11,east,WidgetC,42.00,1
7,2026-03-02,north,WidgetA,180.40,4
8,2026-03-15,west,WidgetC,99.99,3
9,2026-03-21,east,WidgetA,76.20,2
10,2026-03-30,north,WidgetB,145.60,3
EOF
$ cat > regions.csv <<'EOF'
region,country,manager
east,China,Li
west,China,Wang
north,China,Zhao
EOF
5.3 一次性查询
-header 让首行作为列名,表名就是文件名基名 sales:
$ textql -sql "select * from sales limit 3" -header sales.csv
1,2026-01-03,east,WidgetA,120.5,3
2,2026-01-04,east,WidgetB,89.9,1
3,2026-01-05,west,WidgetA,210,5
短 SQL 语法(单表省略 select/from):
$ textql -sql "count(*)" -header sales.csv
10
5.4 聚合与跨文件 JOIN
$ textql -sql "select region, count(*) cnt, round(sum(amount),2) total from sales group by region order by total desc" -header sales.csv
west,3,620.74
north,3,381.25
east,4,328.6
$ textql -sql "select s.region, r.country, r.manager, round(sum(s.amount),2) total from sales s join regions r on s.region = r.region group by 1,2,3" -header sales.csv regions.csv
east,China,Li,328.6
north,China,Zhao,381.25
west,China,Wang,620.74
5.5 stdin 管道查询
管道进来的数据表名固定为 stdin:
$ cat sales.csv | textql -sql "select region, round(sum(amount),2) from stdin group by region" -header
east,328.6
north,381.25
west,620.74
⚠️ 注意:官方 README 的管道示例写的是
from pipe,实测报no such table: pipe——正确表名是stdin。这是照抄 README 的新手最常踩的第一个坑。
六、适用场景与限制
适合:
- 服务器上对导出的 CSV/TSV/日志文本做一次性即席聚合,不想装数据库、也不想学新 SQL 方言(就是标准 SQLite);
- 管道中间环节:上游
grep/awk过滤后的文本直接交给 TextQL 出统计(实测grep -v north sales.csv | textql -sql "select region, count(*) from stdin group by region"正常); - 需要把文本"升级"成 SQLite 库继续用别的工具查(
-save-to)或进官方 REPL(-console); - 对二进制体积敏感的场景:4.3 MB,同类工具里最小之一。
限制(实测确认):
- 停更:GitHub release 停在 2015-12-17 且无预编译二进制,master 停在 2023-10-22;发行包冻结在
2.0.3-4build1(2015 代码,无-sqlfile、版本串空),新功能必须自备 Go+CGO 工具链构建;bug 无人修(本文实测就撞上 3 个未修复缺陷,见下); - 无法指定列类型:所有列一律 NUMERIC,
-save-to落盘的库.schema全是 NUMERIC,数值/文本混排列有隐患; - 已知缺陷(实测复现):① SQL 以"分号+换行"结尾触发无限循环输出(8 秒灌出 73 MB 后
timeout杀掉);② 无-sql/-sqlfile或-sqlfile指向不存在文件时,打印 Usage/错误后输出内存指针(如2026-11-03 04:50:53 0xc000045ef0,log.Fatalln(*error)传指针所致);③go install产物-version打印空行(VERSION 未注入); - 只读源文件:
INSERT/UPDATE只改内存库,不能回写 CSV; - 无自研交互壳:
-console是 fork 系统 sqlite3,要求 PATH 有sqlite3且拒绝管道输入; - 无配置文件体系:全部行为由命令行参数决定,不存在
.textql/config.json之类的持久化配置(详见《TextQL 2.0.3 配置参数详解》第二章的源码级论证)。
七、同类选型对比
社区指标取自 GitHub 仓库页与 shields.io,查询日期 2026-11-03;功能结论取自各项目仓库描述与本文实测。
| 工具 | 仓库 | Stars | 许可证 | 最新 release | 最后提交 | 定位(仓库描述) |
|---|---|---|---|---|---|---|
| TextQL | dinedal/textql | 9.1k | MIT | 2.0.3(2015-12,无二进制) | 2023-10 | easily execute SQL against structured text like CSV or TSV |
| csvq | mithrandie/csvq | 1.6k | MIT | v1.18.1(2023-03,有 Linux 包) | 2023-03 | SQL-like query language for csv |
| dsq | multiprocessio/dsq | 3.9k | Apache-2.0 | v0.23.0(有 Linux 包) | 2023-09 | running SQL queries against JSON, CSV, Excel, Parquet, and more |
| trdsql | noborus/trdsql | 2.2k | MIT | v1.2.3(持续发版) | 活跃(2026 年仍在提交) | execute SQL queries on CSV, LTSV, JSON, YAML and TBLN |
| OctoSQL | cube2222/octosql | 5.3k | MPL-2.0 | v0.13.0 | 2024-05 | join, analyse and transform data from multiple databases and file formats using SQL |
| sqlite3 CLI | 官方发行 | — | public domain | 系统自带 3.37.2 | 极活跃 | .import CSV 后查询 |
关键差异解读与选型建议:
- 要"装完即用、长期有人修":选 trdsql(2026 年仍发版)或 dsq——TextQL 的 GitHub release 无任何预编译包,Ubuntu 发行包冻结在 2015 代码,要用新功能就得自备 Go+CGO 构建;
- 要"文件即表、原地回写":选 csvq——TextQL 只读源文件,csvq 的 UPDATE/CREATE TABLE AS 直接落盘且带事务;
- 要"格式覆盖最广(JSON/Excel/Parquet)":选 dsq——TextQL 只认分隔符文本;
- 要"完整 SQLite 方言 + 最小二进制 + 官方 REPL 直通":TextQL 仍是顺手的——它把数据直接交给真 SQLite 执行,
strftime/窗口函数/CTE 全可用,-save-to产物就是标准.sqlite,-console就是官方 sqlite3 shell;同类工具里只有它"零方言损耗"; - 对比 sqlite3 原生
.import:sqlite3 预装率高、SQL 最权威,但.import不吃 stdin、表头/分隔符/类型都要手工调(-csv模式仍把所有列建 TEXT),而 TextQL 一条命令完成"载入+推断+查询"。已有 sqlite3 且数据是规整 CSV 时.import够用;频繁处理管道/异构分隔符文本时 TextQL 省事。
结论:2026 年的今天,新项目不建议首选 TextQL——停更十年、无二进制、实测存在会刷爆磁盘的无限循环缺陷;同等需求优先 trdsql(活跃+后端可选)或 csvq(可回写)。TextQL 的现实价值在于:存量脚本仍在大量使用(9k+ star 的生态惯性)、需要标准 SQLite 方言与 4.3 MB 极简部署的临时查询,以及作为"CSV→SQLite 桥"把数据交给 sqlite3 工具链续用。
八、参考链接
- 官方仓库:https://github.com/dinedal/textql
- 发布页(2.0.3,2015-12-17):https://github.com/dinedal/textql/releases/tag/2.0.3
- 最后提交(PR #141 加 -sqlfile):https://github.com/dinedal/textql/commit/e6545d501ca9
- man 手册:https://github.com/dinedal/textql/blob/master/man/textql.1.ronn
- 扩展函数库:https://github.com/dinedal/go-sqlite3-extension-functions
- 同类项目:https://github.com/mithrandie/csvq 、https://github.com/multiprocessio/dsq 、https://github.com/noborus/trdsql 、https://github.com/cube2222/octosql
- 本专栏后续篇:《Ubuntu 22.04 安装 TextQL 2.0.3 指南》、《TextQL 2.0.3 配置参数详解》、《TextQL 2.0.3 常用 CLI 命令与工具详解》