
在 DuckDB 中读取 CSV 时,若某列存在类型不一致(如多数为数字、个别为字符串 ID),可通过 dtype(Python API)或 types(CLI/SQL)参数显式指定字段类型,避免自动推断失败。
在 duckdb 中读取 csv 时,若某列存在类型不一致(如多数为数字、个别为字符串 id),可通过 `dtype`(python api)或 `types`(cli/sql)参数显式指定字段类型,避免自动推断失败。
当使用 DuckDB 读取 CSV 文件时,其默认启用智能类型推断(autodetection),能高效识别数值、字符串、时间等常见类型。但该机制对混合类型列(例如 id 列中大部分是整数,却夹杂 'ABC123' 这类字符串)往往失效——可能报错、截断、或错误地将全部值转为 NULL。此时,显式声明列类型是最可靠、最轻量的解决方案。
✅ 正确做法:使用 dtype 参数(Python)或 types(SQL)
在 Python 环境中(推荐方式),调用 duckdb.read_csv() 时传入 dtype 字典,键为列名,值为 DuckDB 支持的类型字符串(如 'VARCHAR'、'BIGINT'、'DATE' 等):
import duckdb
# 强制 'id' 列为字符串类型,其余列保持自动推断
df = duckdb.read_csv('stations-2023-09.csv', dtype={"id": "VARCHAR"})
# 可直接链式操作(如查看前5行)
result = df.limit(5).to_df() # 转为 pandas DataFrame 查看
print(result.dtypes)
# 输出示例:id object ← 表明已成功作为字符串加载
⚠️ 注意:DuckDB 的 Python API 必须使用
dtype(非types),否则会静默忽略或抛出TypeError;而 CLI 或 SQL 模式中(如SELECT * FROM read_csv(...))则使用types参数。
? 类型名称规范(关键!)
DuckDB 接受标准 SQL 类型别名,常用字符串类型包括:
-
'VARCHAR'(推荐,默认不限长度,兼容性最佳) -
'TEXT'(等价于VARCHAR) -
'CHAR(N)'(定长,慎用,N 需明确指定)
❌ 错误写法示例(会导致类型未生效):
# ❌ 错误:使用 Python 类型名(str/int)或小写类型
dtype={"id": "str"} # 不识别
dtype={"id": "string"} # DuckDB 不支持此关键字
dtype={"id": "varchar"} # 小写可能被忽略(建议大写确保兼容)
✅ 正确写法始终使用 大写标准 SQL 类型:
dtype={"id": "VARCHAR", "code": "TEXT", "uic": "BIGINT"}
? 扩展技巧:批量指定与类型校验
若需统一将多列为字符串(如所有 ID、编码类字段),可批量设置:
# 将多个字段强制设为 VARCHAR
string_cols = ["id", "code", "slug", "type"]
dtype = {col: "VARCHAR" for col in string_cols}
df = duckdb.read_csv("data.csv", dtype=dtype)
此外,可在加载后快速验证类型是否生效:
print(df.description) # 查看 DuckDB 内部类型(含 varchar/int64 等) # 或转换为 pandas 后检查 print(df.to_df().dtypes)
? 总结
-
核心机制:
dtype(Python)或types(SQL)参数覆盖自动推断,无需预处理 CSV; -
类型书写:务必使用大写标准 SQL 类型(如
"VARCHAR"),避免小写或 Python 类型名; - 优势:零内存拷贝、无中间文件、支持超大 CSV 流式解析;
-
适用场景:ID 混合格式、带前导零编号(如
"00123")、空值占位符(如"N/A")、多语言字符异常等。
通过这一方法,你既能保留数据原始语义(如 id="ABC-789" 不被误转为 NULL),又能无缝接入 DuckDB 的高性能查询与分析流水线。











