TextQL 介绍与选型指南

TextQL 是 dinedal 开发的 Go 单二进制工具,把 CSV/TSV 等分隔符文本直接载入 SQLite 内存库执行 SQL,本文实测 2.0.3(master 源码构建)的安装与查询能力,如实呈现其 2015 年后停更状态,并与 csvq/dsq/trdsql/OctoSQL/SQLite 做量化选型对比

TextQLTextQLGoSQLiteSQLCSVCLI工具2026/11/03

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;sqlite3 3.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 / Watchers9,093 / 155
许可证MIT
最新 release2.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,全程单进程、无外部服务:

  1. 输入层(inputs.CSVInput):按 -dlm 指定的分隔符与 -header 开关逐行解析文件;表名自动取文件名基名(sales.csv → sales),可用 名字:文件 语法覆写;目录参数非递归展开为其中每个文件;stdin 有管道数据时自动作为一个输入表载入。
  2. 存储层(storage):基于 mattn/go-sqlite3 创建内存 SQLite 库,每个输入文件建一张表;所有列一律建为 NUMERIC 类型,由 SQLite 亲和性对每个值动态推断(实测 typeof() 同列可返回 real/text/integer)。若系统存在可选的 libgo-sqlite3-extension-functions.so,启动时自动加载(stdev/median 等聚合扩展)。
  3. SQL 层:-sql/-sqlfile 的语句按分号拆分后原样交给 SQLite 执行——TextQL 没有自研引擎,因此完整 SQLite 方言可用(strftime、窗口函数、CTE、JOIN 等),这是它与同类工具最大的能力差异。
  4. 输出层(outputs):CSVOutput(按 -output-dlm 分隔)与 PrettyCSVOutput(-pretty,tablewriter 框线表)两种,写 stdout 或 -output-file。
  5. 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) 对文本日期列直接生效
内置 regexpWHERE 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最后提交定位(仓库描述)
TextQLdinedal/textql9.1kMIT2.0.3(2015-12,无二进制)2023-10easily execute SQL against structured text like CSV or TSV
csvqmithrandie/csvq1.6kMITv1.18.1(2023-03,有 Linux 包)2023-03SQL-like query language for csv
dsqmultiprocessio/dsq3.9kApache-2.0v0.23.0(有 Linux 包)2023-09running SQL queries against JSON, CSV, Excel, Parquet, and more
trdsqlnoborus/trdsql2.2kMITv1.2.3(持续发版)活跃(2026 年仍在提交)execute SQL queries on CSV, LTSV, JSON, YAML and TBLN
OctoSQLcube2222/octosql5.3kMPL-2.0v0.13.02024-05join, 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 工具链续用。

八、参考链接