Excel 扩展
excel 扩展通过封装 i18npool library 提供按 Excel 格式规则格式化数字的函数,并支持读写 Excel(.xlsx)文件。请注意不支持 .xls 文件。
提示:此前,Excel 文件读写由
spatial扩展处理,它通过依赖“顺带”支持了 XLSX,但该能力未来可能从spatial中移除。相比之下,excel扩展更高效且对导入/导出流程控制更细。如果excel扩展无法满足你的场景,可尝试spatial扩展。可参考 Excel Import 与 Excel Export 页面,但请注意这些特性未来也可能被弃用。
安装与加载
excel 扩展首次使用时会从官方扩展仓库自动按需加载。
若要手动安装并加载,请执行:
INSTALL excel;
LOAD excel;
Excel 标量函数
| 函数 | 说明 |
|---|---|
excel_text(number, format_string) | 按 format_string 规则格式化给定 number |
text(number, format_string) | excel_text 的别名 |
示例
SELECT excel_text(1_234_567.897, 'h:mm AM/PM') AS timestamp;
| timestamp |
|---|
| 9:31 PM |
SELECT excel_text(1_234_567.897, 'h AM/PM') AS timestamp;
| timestamp |
|---|
| 9 PM |
读取 XLSX 文件
读取 .xlsx 文件最简单的方式就是直接对其 SELECT,例如:
SELECT *
FROM 'test.xlsx';
| a | b |
|---|---|
| 1.0 | 2.0 |
| 3.0 | 4.0 |
如果需要设置更多选项来控制导入过程,可使用 read_xlsx 函数。支持以下命名参数。
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
header | BOOLEAN | automatically inferred | 是否将首行视为结果列名。 |
sheet | VARCHAR | automatically inferred | 要读取的 xlsx 工作表名称。默认读取第一个工作表。 |
all_varchar | BOOLEAN | false | 是否将所有单元格都读取为 VARCHAR。 |
ignore_errors | BOOLEAN | false | 是否忽略错误,并将无法转换为推断列类型的单元格静默替换为 NULL。 |
range | VARCHAR | automatically inferred | 要读取的单元格范围(电子表格表示法)。例如 A1:B2 读取 A1 到 B2。若未指定,则会推断为:从第一行连续非空单元格开始,到覆盖相同列范围的第一行空行结束的矩形区域。 |
stop_at_empty | BOOLEAN | automatically inferred | 遇到空行时是否停止读取。若显式提供 range,默认 false;否则默认 true。 |
empty_as_varchar | BOOLEAN | false | 自动推断列类型时,是否将空单元格视为 VARCHAR 而不是 DOUBLE。 |
SELECT *
FROM read_xlsx('test.xlsx', header = true);
| a | b |
|---|---|
| 1.0 | 2.0 |
| 3.0 | 4.0 |
此外,也可使用带 XLSX 格式选项的 COPY 语句将 Excel 文件导入现有表。此时会使用目标表列类型来约束 Excel 单元格类型转换。
CREATE TABLE test (a DOUBLE, b DOUBLE);
COPY test FROM 'test.xlsx' WITH (FORMAT xlsx, HEADER);
SELECT * FROM test;
类型与范围推断
由于 Excel 本质上只在单元格中存储数字或字符串,且不强制同一列单元格类型一致,excel 扩展在导入工作表时需要进行一定“推断”来决定列类型。虽然绝大多数列会被推断为 DOUBLE 或 VARCHAR,但有以下注意点:
- 在可能时,会根据单元格应用的 format 推断
TIMESTAMP、TIME、DATE、BOOLEAN。 - 包含
TRUE和FALSE的文本单元格会被推断为BOOLEAN。 - 空单元格默认视为
DOUBLE;若empty_as_varchar设为true,则视为VARCHAR。
若 all_varchar 设为 true,上述规则均不生效,所有单元格都按 VARCHAR 读取。
当未显式指定类型时(例如使用 read_xlsx 而不是 COPY TO ... FROM '⟨file⟩.xlsx'),
结果列类型会根据工作表第一条“数据行”推断,即:
- 若未显式给出 range
- 若检测到表头或通过
header强制表头,则取表头后的第一行 - 若未检测到或未强制表头,则取工作表第一行非空行
- 若检测到表头或通过
- 若显式给出 range
- 若第一行存在表头或通过
header强制表头,则取 range 第二行 - 若无表头,则取 range 第一行
- 若第一行存在表头或通过
如果第一条“数据行”不能代表整张表(例如包含空单元格),可能会导致问题。此时可用 ignore_errors 或 empty_as_varchar 规避。
但当使用 COPY TO ... FROM '⟨file⟩.xlsx' 语法时,不会进行类型推断,结果列类型由目标表列类型决定。所有单元格仅通过从 DOUBLE 或 VARCHAR 到目标列类型的 cast 转换。
写入 XLSX 文件
可使用 COPY 语句并将格式指定为 XLSX 来写入 .xlsx 文件。支持以下附加参数。
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
header | BOOLEAN | false | 是否将列名写为工作表第一行 |
sheet | VARCHAR | Sheet1 | 要写入的 xlsx 工作表名称 |
sheet_row_limit | INTEGER | 1048576 | 单个工作表最大行数。超出该限制会抛出错误。 |
警告:许多工具单个工作表最多只支持 1,048,576 行,因此提高
sheet_row_limit可能导致结果文件无法被其他软件读取。
这些参数在 COPY 语句中作为 FORMAT 后的选项传入,例如:
CREATE TABLE test AS
SELECT *
FROM (VALUES (1, 2), (3, 4)) AS t(a, b);
COPY test TO 'test.xlsx' WITH (FORMAT xlsx, HEADER true);
类型转换
由于 XLSX 文件本质上只支持存储数字或字符串(对应 VARCHAR 与 DOUBLE),写入 XLSX 时会应用以下类型转换规则。
- 数值类型写入 XLSX 时会 cast 为
DOUBLE。 - 时间类型(
TIMESTAMP、DATE、TIME等)会转换为 Excel “序列值”:日期为自 1900-01-01 起的天数,时间为一天中的分数;随后应用“数字格式”,以便在 Excel 中显示为日期/时间。 TIMESTAMP_TZ与TIME_TZ分别 cast 为 UTCTIMESTAMP与TIME,时区信息会丢失。BOOLEAN会转换为1与0,并应用“数字格式”,使其在 Excel 中显示为TRUE与FALSE。- 其余类型都会 cast 为
VARCHAR后写入为文本单元格。