数据源
DuckLocal 把文件变成视图,挂到内存中的 DuckDB 连接上;打开了数据库文件时,就挂到那个数据库文件里。旁边还可以再附加其他数据库。不需要任何配置。
打开数据的方式
以下入口都走同一套解析规则:
- 命令行中的路径:
ducklocal ./logs/ billing.parquet - 标题栏的 打开 菜单:打开文件、打开文件夹,或 输入路径或通配符——后者会打开 打开数据 对话框,可以手动输入路径,也可以用系统文件选择器选取
- 把文件或文件夹拖到窗口的任意位置
- 在 Mac 上,由访达交给 DuckLocal 的文件,见从访达打开
如果想在当前数据库旁边再加一个数据库、而不是替换它,用 打开 → 附加数据库…,见附加数据库。
在 macOS 上,还可以在访达里双击打开 Parquet 和 DuckDB 文件;选中 Parquet、DuckDB、CSV、TSV 或 JSON Lines 文件按空格键,“快速查看”会显示它的前几行,不用启动 DuckLocal。
支持的文件格式
扩展名不区分大小写。
| 扩展名 | 读取方式 |
|---|---|
.csv, .tsv, .txt | read_csv_auto 视图 |
.parquet | read_parquet 视图 |
.json, .ndjson, .jsonl | read_json_auto 视图 |
.xlsx, .xls, .xlsb, .ods | 每个工作表导入为一张表 |
.json.gz、.csv.gz 这类 gzip 文本也算数据文件,适用于 schema、source block 和挂载文件;logs.json.gz 会成为名为 logs 的视图。0.4.0 之前,ducklocal schema 会把这种文件当作数据库尝试打开;如果你用的是旧版,请在 SQL 里用 read_json 或 read_csv 读取。
其他扩展名都不算数据文件,参见数据库文件。
工作簿是唯一会转换为表而非视图的格式,并且会导入所有工作表。第一个工作表以文件名主干(去掉扩展名的部分)命名,其余工作表命名为 {主干}_{工作表名},空工作表会跳过。列类型根据单元格内容推断:整数为 BIGINT,整数与浮点数混合为 DOUBLE,日期为 TIMESTAMP,其他混合或无法识别的内容为 VARCHAR;空单元格导入为 NULL。
文件夹与通配符
文件夹会递归遍历,其中每个数据文件都变成一个视图。遍历遵循两条规则:
- 跳过隐藏条目(名字以
.开头),也不进入其下的子目录。 - 不跟随符号链接。指向上层目录的链接会让遍历没完没了;而链接指向的目录,通常会在它实际所在的位置遍历到。
文件按排序后的顺序挂载,所以同一个文件夹每次得到的工作区都一样。
通配符可以包含 *(任意一串字符)和 ?(恰好一个字符)。匹配按路径逐段、直接在文件系统上进行,所以通配符可以跨目录:
ducklocal './data/2026-0*/*.parquet'没有转义字符。** 没有特殊含义,效果和单个 * 一样,不会递归。通配符匹配到的目录会被忽略,只挂载文件。这里同样跳过隐藏条目。
不加引号的通配符会先由 shell 展开,DuckLocal 拿到的是展开后的结果。这样没问题。只有想让 DuckLocal 自己展开时才需要加引号——比如 shell 匹配不到文件、不加引号就会报错的情况。
一次读取多个 CSV
DuckLocal 挂载的每个文件都是独立的视图,schema 各自嗅探,所以两个结构不一致的 CSV 互不干扰。麻烦出在一条 SQL 同时读取多个文件的时候:
SELECT * FROM read_csv('data/*.csv', union_by_name = true)各文件嗅探出的类型可能对不上。 读取函数根据样本推断列类型。某列在其他文件里都是数值,只在一个文件里混进了字符串
'NULL',整个读取就会报转换错误。这时在SELECT里做 cast 已经来不及,因为出错的是读取这一步。应该把所有列按文本读入,再在 SQL 里转换:sqlSELECT try_cast(amount AS DOUBLE) AS amount FROM read_csv('data/*.csv', union_by_name = true, all_varchar = true)union_by_name = true还能兼容列不完全相同的文件。字符串
'NULL'不是NULL。 CSV 里写着的'NULL'(或'N/A'、'null')只是普通文本,WHERE amount IS NOT NULL过滤不掉。可以用NULLIF(amount, 'NULL'),或者WHERE amount <> 'NULL'。
两种修法可以叠加:try_cast(NULLIF(amount, 'NULL') AS DOUBLE)。
数据库文件
DuckLocal 同一时间只有一个主数据库:要么在内存里,要么是你打开的 DuckDB 文件。数据文件变成主数据库里的视图。此外还可以在旁边附加其他数据库。
只要路径存在且不是数据文件,就会作为主数据库打开,不会挂载成视图。扩展名无所谓:.db、.duckdb,甚至 .md 路径都会当作数据库,能不能真正打开由 DuckDB 决定。
由此有几点需要知道:
- 只有“打开数据”对话框能新建数据库。 输入一个以
.duckdb结尾、还不存在的路径,DuckLocal 会创建这个数据库,缺少的父目录也一并创建。其他入口——命令行、文件选择器、拖放、访达——遇到不存在的路径都会报文件不存在。 - 打开数据库会替换主数据库。 已登记的文件和附加的数据库会重新挂到新连接上。S3 凭据不会保留,需要重新配置。
- 文件打不开时,DuckLocal 会说明原因(见下文)。启动时它会退回内存模式的工作区,不会启动失败;运行期间打开失败,原来的工作区保持不变。
- 已经附加在主数据库旁边的文件,会先分离,再作为主数据库打开;打开失败的话,附加会恢复原样。打开的正是当前主数据库文件时,直接沿用,不会重复打开。
打开数据库文件后再挂载数据文件,会把这些视图写进那个数据库文件,视图会一直保存在那里,不只存在于本次会话。
数据库文件打不开时
DuckDB 拒绝打开某个文件时,DuckLocal 会自己读取文件开头的几个字节;如果能从中看出原因,就把原因和解决办法放在 DuckDB 原始报错的上方。DuckDB 的原始报错保留在下面,方便查看确切错误。说明文字跟随界面语言。
| 文件是什么 | DuckLocal 的说明 |
|---|---|
| 由比 DuckLocal 内置版本更新的 DuckDB 写入的 DuckDB 文件 | 写明两个版本号,并给出一段 SQL,在那个较新的 DuckDB 里运行,把文件复制成 DuckLocal 能读的格式(见下) |
| 来自 v0.9 或更早版本的 DuckDB 文件 | 用原来的 DuckDB 执行 EXPORT DATABASE 'dir',再在 DuckLocal 里执行 IMPORT DATABASE 'dir' |
| SQLite 数据库 | 它不是 DuckDB 文件,应该附加它——用附加数据库…,或者 INSTALL sqlite; ATTACH '…' (TYPE sqlite); |
| 其他不是 DuckDB 文件的东西 | CSV、Parquet、JSON、Excel 文件请作为数据文件打开 |
对于较新 DuckDB 写的文件,提示里会填好文件路径和 DuckLocal 内置的 DuckDB 版本。在创建该文件的那个 DuckDB 里运行,然后打开 compat.duckdb:
ATTACH '/path/to/file.duckdb' AS src (READ_ONLY);
ATTACH 'compat.duckdb' AS dst (STORAGE_VERSION 'v2.0.0');
COPY FROM DATABASE src TO dst;DuckDB v1.2 之前写入的文件不记录是哪个版本创建的。其他原因的失败——文件被别的程序锁住、没有读取权限等——只显示 DuckDB 的原始报错。参见常见问题排查。
哪些 DuckDB 能读这个数据库
打开数据库文件后,状态栏会显示它的路径。把鼠标悬停在上面,可以看到文件的存储格式,也就是能读它的最低 DuckDB 版本,例如 存储格式:DuckDB v1.0.0+ 可读;文件里有记录时,还会显示创建它的版本(由 DuckDB v1.4.3 创建)。把文件交给使用旧版 DuckDB 的人之前,先看一眼这里。
DuckLocal 用的是 DuckDB 2.0,但它新建的数据库文件按 DuckDB 1.x 的格式写入(DuckDB v1.0.0+ 可读),所以 DuckDB 1.x 的命令行、Python 或 DBeaver 仍然能打开。其他程序按 DuckDB 2.0 自己的格式(v2.0.0+)写的文件也能打开,并保持原格式:1.x 读不了这种文件。
附加数据库
把另一个 DuckDB 或 SQLite 文件附加在主数据库旁边,就能跨库查询——比如把一份快照和今天的数据放在一起比。
- 打开标题栏的 打开 菜单,选择 附加数据库…。
- 输入路径,或点击 浏览 选择文件。
- 除非确实要修改这个文件,否则保持勾选 只读。它默认是勾选的。
- 点击 附加。
数据库会根据文件名得到一个别名,用 别名.表(或 别名.schema.表)查询其中的表:
-- snap-2026-10-01.duckdb 附加后的别名是 snap_2026_10_01
SELECT t.id, t.amount, s.amount AS amount_last_week
FROM orders t
JOIN snap_2026_10_01.orders s USING (id);别名的生成规则:
- 取文件名主干,其中不是 ASCII 字母或数字的字符都换成
_。 - 不以字母开头时,前面加
db_:2026-10 logs.duckdb变成db_2026_10_logs。 - 名字已被占用时加序号:
snap,然后是snap_2。不会使用main。 - 以后再次附加同一个文件,会拿回它原来的别名,针对它写好的 SQL 照样能跑。
其他细节:
- SQLite 文件根据文件内容识别,通过 DuckDB 的
sqlite扩展附加。 - **取消勾选“只读”**会以可写方式附加。这时如果 DuckDB 路径不存在,会新建一个空数据库;勾选只读时,附加会失败。
- 同一个文件不会附加两次。 附加一个已经打开的文件(不论它是主数据库还是已附加的数据库),会提示 这个数据库已经打开了,名为 …。
在侧栏中
所有数据库都出现在 schema 树里,主数据库和附加的数据库一样,空数据库也列出。数据库名旁边会视情况显示 只读 或 sqlite,鼠标悬停可看到对应的文件。
右键点击数据库:
- 设为默认数据库——执行
USE,之后不带库名的表名都在这里查找。状态栏会显示当前在哪里查找。 - 分离数据库——分离并忘掉它,下次不会再自动附加。如果它正是默认数据库,会先切回主数据库。文件本身不受影响。
右键菜单的其余选项见 Schema 浏览与历史。
跨连接保留
附加的数据库连同别名和只读设置,存放在 DuckLocal 自己的历史数据库里,每次建立新连接时都会重新附加:下次启动时、打开另一个数据库后、以及选择 新建内存数据库 后。
- 文件不存在的数据库会悄悄跳过。登记仍然保留,文件回来后它也会回来——DuckLocal 不会在原位置建一个空数据库。
- 已经打开的数据库(不论是作为主数据库还是别的方式)不会再附加一次。
- 如果新的主数据库里已经有同名的数据库,DuckLocal 会提示 无法附加 …:名称 … 已被当前数据库占用。
从访达打开
在 Mac 上,访达可以直接把文件交给 DuckLocal:
| 文件 | 双击 | “打开方式”,或拖到程序坞图标上 |
|---|---|---|
.parquet | 在 DuckLocal 中打开 | 可以 |
.duckdb、.ddb | 在 DuckLocal 中打开 | 可以 |
.dash | 在 DuckLocal 中打开 | 可以 |
.csv、.tsv、.json、.jsonl、.ndjson、.xlsx、.xls | 仍由原来打开它们的应用处理(Numbers、Excel、文本编辑器) | 可以 |
DuckLocal 只把自己注册为 Mac 上没有其他应用认领的格式的默认应用。如果 Parquet 或 DuckDB 文件已经被别的应用占了,就在 打开方式 里选 DuckLocal;或者在访达里用 显示简介 → 打开方式 → 全部更改… 把它设为默认。
从访达来的文件,处理方式和拖到窗口上完全一样:数据文件变成当前工作区里的视图,数据库文件作为主数据库打开,.dash 文件作为仪表盘标签页打开。如果 DuckLocal 没在运行,会先启动,等它自己的启动流程完成后再打开这个文件。
快速查看(Quick Look)预览
在 Mac 上,在访达里选中数据文件后按空格键,不用打开任何应用就能看到它的列和前几行。预览功能内置在 DuckLocal.app 里,不需要另外安装。和应用本身一样,需要 macOS 12 或更新版本。
| 文件 | 预览内容 |
|---|---|
.parquet | 列和类型、前 50 行,以及文件尾部(footer)里的信息:行数、行组数、压缩方式、写入程序 |
.duckdb、.ddb | 表的数量、存储格式(Readable by DuckDB …),以及最大的五张表,每张表附估算行数和前 50 行 |
.csv、.tsv | 列及嗅探出的类型、前 50 行——以表格显示,而不是纯文本 |
.jsonl、.ndjson | 列和前 50 行 |
普通 .json 和 Excel 文件仍由 macOS 自带的预览处理。
预览会做什么、不会做什么:
- 从不写入。数据库以只读方式附加。
- 从不扫描整个文件:行数据用
LIMIT读取,只有格式本身存了行数时才显示行数(Parquet 的文件尾部、数据库的估算值)。 - 不下载任何东西:既不安装也不加载 DuckDB 扩展。
- 超过 200 个字符的单元格会被截断。预览页面的文字是英文。
- 读不了的文件会显示一页说明原因。
按空格键后没有出现 DuckLocal 的预览时:
- 确认 DuckLocal 在 应用程序 文件夹里,并启动一次。macOS 第一次见到这个应用时才会登记预览功能。
- 在终端里重置快速查看:
qlmanage -r,然后再试一次。 - 在“系统设置”的扩展设置里,确认快速查看下的 DuckLocal Preview 已开启。
命名
文件对应的视图以文件名主干命名,并整理成合法的标识符。名字在连接中已被占用时,DuckLocal 会加上序号:events,然后是 events_2、events_3。所以两个文件即使在不同目录、主干同名,也会得到不同的视图。
判断是否重复,看的是写出来的路径文本,所以 ./a.csv 和 a.csv 算两个不同的文件。
限制
- 每次打开最多 256 个数据文件。 上限按一次请求里的所有路径合计,不按文件夹分别计算。这样即使不小心把整个用户主目录拖进来,连接也不会被占上好几分钟。达到上限时,DuckLocal 会给出提示,只挂载前 256 个文件。
- 启动时重新挂载上次会话的文件,不受这个上限限制。
管理已注册的数据源
已注册的文件列在侧栏的本地文件分组里,每个文件显示视图名、文件名和行数。选中文件会生成一条查询它的 SELECT 语句。
点文件行上的 ×,确认后即可移除。移除会删除视图、清除这条注册;文件本身不受任何影响。
刷新 schema 会重新加载目录(catalog)和已注册的文件。
会被记住的内容
已注册文件的清单(路径、视图名和类型)存放在 DuckLocal 自己的历史数据库里,下次启动时重新挂载,所以关掉时是什么工作区,再打开还是什么工作区。附加的数据库也一样。主数据库文件本身不会记住:除非指定了数据库,每次启动都从内存模式开始。
这些数据在磁盘上的位置,参见设置与应用数据。
