支持的数据类型

更新时间:
复制 MD 格式

云原生DuckDB列存表需要在 PostgreSQL 和 DuckDB 之间完成建表映射、写入转换及查询结果转换。本文说明可用于建表和写入的类型、精度及数组限制,用于根据数据特征选择合适的列类型。未列出的类型即使偶尔能够建表,也不能视为受支持。

类型声明语法

CREATE TABLE table_name (
  column_name data_type
  [, ...]
) USING duckdb;

参数

  • column_name:列名称。

  • data_type:类型修饰符,例如 varchar(n)、numeric(p,s) 和 bit(n),先由 PostgreSQL 检查,再映射到 DuckDB。取值范围:

标量类型

类别

PostgreSQL 类型

DuckDB 物理类型或说明

布尔

boolean

BOOLEAN

整数

smallint、integer、bigint

对应的有符号整数

对象标识

oid

无符号 32 位整数

定点数

numeric(p,s)、decimal(p,s)

当 p <= 38 时映射为 DECIMAL(p,s);其他情况见NUMERIC 和 DECIMAL章节

浮点数

real、double precision

FLOAT、DOUBLE

货币

money

DuckDB BIGINT,按 PostgreSQL 内部 64 位金额值保存

内部字符

PostgreSQL 内部 "char"

DuckDB VARCHAR,保存一个字节

字符串

character(n)、varchar(n)、text、name

DuckDB VARCHAR

二进制

bytea

BLOB

位串

bit(n)、bit varying(n)

BITSTRING

日期时间

date、time、timetz、timestamp、timestamptz、interval

对应的 DuckDB 日期时间类型

标识符

uuid

UUID

JSON

json、jsonb

JSON

XML

xml

VARCHAR

扩展类型

roaringbitmap

安装对应类型扩展后映射为 BLOB

二进制、位串、JSON 和 XML 的存取行为说明见BYTEA、BIT、JSON 和 XML章节,日期时间类型的时区与无穷值行为见日期、时间和时区章节。

示例

CREATE TABLE columnar_type_example (
  id bigint,
  amount numeric(18, 4),
  ratio double precision,
  enabled boolean,
  label text,
  payload jsonb,
  raw bytea,
  event_time timestamptz,
  request_id uuid
) USING duckdb;

NUMERIC 和 DECIMAL

语法

numeric [ ( precision [, scale ] ) ]
decimal [ ( precision [, scale ] ) ]

参数

  • precision:有效数字总位数,DuckDB DECIMAL 最大为 38

  • scale:小数位数,负 scale 不受支持

说明

没有声明精度的 numeric,以及精度大于 38 的声明,使用 polar_csi.decimal_default 指定的 DuckDB 类型,默认值为 DECIMAL(38,10)。

使用说明

建议优先声明精度和小数位数:

amount numeric(18, 2)
  • numeric(p,s) 在 p <= 38 且 scale 有效时映射为与声明一致的 DECIMAL(p,s)。未声明精度的 numeric 默认只有 10 位小数,超过目标小数位数(即声明的 scale 或 polar_csi.decimal_default 指定的小数位数)的小数位会丢失,超出目标整数位范围的值会报转换错误。

  • PostgreSQL numeric 的 NaN、Infinity 和 -Infinity 不能表示成 DuckDB DECIMAL,INSERT 路径会把这些非有限值写成 NULL,应避免向列存 numeric 列写入非有限值。

  • 浮点类型 real 和 double precision 可以保存浮点 NaN 和无穷值,它们与 numeric 的行为不同。

数组类型

语法

element_type[]

支持下列一维数组:

  • boolean[]

  • smallint[]、integer[]、bigint[]、oid[]

  • numeric[]、real[]、double precision[]

  • character[]、varchar[]、text[]

  • date[]、time[]、timetz[]、timestamp[]、timestamptz[]、interval[]

  • uuid[]、bytea[]

  • json[]、jsonb[]

示例:

数组可以为空,也可以包含 NULL 元素:

CREATE TABLE columnar_array_example (
  id integer,
  values integer[],
  labels text[]
) USING duckdb;

INSERT INTO columnar_array_example VALUES
  (1, ARRAY[1, NULL, 3], ARRAY['a', 'b']),
  (2, ARRAY[]::integer[], NULL);

数组维度和下界

DuckDB 列存数组只保存一维、下界为 1 的值。以下两种写入会报错。多行 INSERT 中任一行触发该类错误时,整条语句失败并回滚,已处理的行不会保留。

  • 多维数组不受支持:

    INSERT INTO columnar_array_example
    VALUES (3, ARRAY[[1, 2], [3, 4]], NULL);
    ERROR:  multidimensional arrays are not supported on duckdb tables
    DETAIL:  The array has 2 dimensions, but DuckDB storage only supports empty or one-dimensional arrays.
  • 下界不是 1 的数组不受支持:

    INSERT INTO columnar_array_example
    VALUES (4, '[5:7]={10,20,30}'::integer[], NULL);
    ERROR:  array lower bounds other than 1 are not supported on duckdb tables
    DETAIL:  The array lower bound is 5, but DuckDB storage only supports lower bound 1.

PostgreSQL 内部单字节类型 "char"[] 明确不受支持。它与 SQL 定长字符数组 character[] 不是同一种类型。

numeric[]

未声明精度的 numeric[] 使用 polar_csi.decimal_default 指定的元素类型,默认映射为 DuckDB DECIMAL(38,10)[]。显式声明且精度不超过 38 的 numeric(p,s)[] 保留声明的精度和小数位数。精度大于 38 时使用 polar_csi.decimal_default。

  • 默认 DECIMAL(38,10)[] 映射下,每个元素最多有 38 位有效数字,其中 10 位为小数,超出范围时整条写入报转换错误。

  • NaN、Infinity 和 -Infinity 元素会写成 NULL。

需要超过默认的 10 位小数、超过该范围,或不能接受非有限值变成 NULL 时,不应使用默认映射的 numeric[]。可以把数值拆成标量列、改用受控的整数缩放表示,或以文本保存后显式解析。

日期、时间和时区

  • timestamp 保存无时区时间。

  • timestamptz 保存绝对时间,显示受会话 TimeZone 影响。

  • UPDATE 和 DELETE 中没有时区偏移的 timestamptz 常量,先按当前 PostgreSQL 会话时区解释,再传给 DuckDB。

  • date、timestamp 和 timestamptz 的正负无穷值有专门的转换路径。

示例

对跨时区交换的数据,建议显式设置会话时区,并把偏移写进字面量:

SET timezone = 'UTC';

INSERT INTO columnar_type_example (id, event_time)
VALUES (1, TIMESTAMPTZ '2026-08-26 08:00:00+00');

字符串和排序规则

character(n) 的长度和尾部空格由 PostgreSQL 输入类型检查。DuckDB 的物理 VARCHAR 本身不保存长度。查询中的比较和排序由 DuckDB 执行,PostgreSQL 数据库的 libc 排序规则不会自动成为每个 DuckDB 表达式的排序规则。

对区域设置、大小写或非 ASCII 排序敏感的场景,应使用真实数据验证结果,并为 ORDER BY 显式指定 NULL 顺序。需要严格依赖 PostgreSQL 区域设置语义时,应使用行存表。

BYTEA、BIT、JSON 和 XML

  • bytea 以 DuckDB BLOB 保存,支持 PostgreSQL 输入函数接受的二进制值。

  • bit 和 bit varying 以 DuckDB BITSTRING 保存。

  • json 和 jsonb 可以存取;jsonb 写入时转换成 JSON 文本;JSON 函数只有在 DuckDB 存在兼容实现时才能用于列存查询。

  • xml 以 VARCHAR 文本形式存入 DuckDB,仍会经过 PostgreSQL XML 输入检查,读取时恢复成 PostgreSQL XML。

示例

INSERT INTO columnar_type_example (id, payload, raw)
VALUES (
  2,
  '{"event":"click","ok":true}'::jsonb,
  '\x00ff'::bytea
);

不支持的类型

不支持下列类型类别:

  • Domain 和 Enum

  • 复合类型和 record 列

  • range 和 multirange

  • 几何、网络、全文检索以及其他没有列存转换器的内置类型

  • 未注册列存写入和读取转换的扩展类型。

修改列类型

语法

ALTER TABLE table_name
ALTER COLUMN column_name TYPE data_type;

DuckDB 必须能把所有已有值转换成新类型,且语句不能使用 USING。

示例

ALTER TABLE columnar_type_example
ALTER COLUMN id TYPE numeric(20, 0);

不确定转换是否兼容时,应使用CREATE TABLE AS SELECT创建新列存表并显式转换数据。列存表不支持以另一张列存表作为 INSERT ... SELECT 的数据来源,复制列存表数据请使用CREATE TABLE AS SELECT:

CREATE TABLE columnar_type_example_new
USING duckdb AS
SELECT id::numeric(20, 0), amount::numeric(20, 4)
FROM columnar_type_example;

应用于生产环境

不要把 CREATE TABLE 成功作为类型受支持的依据。生产表至少应验证 NULL、边界值、批量 INSERT、SELECT、UPDATE、COPY 以及备份恢复。