跳到主要内容
跳到主要内容

Variant(T1, T2, ...)

此类型表示其他数据类型的并集。类型 Variant(T1, T2, ..., TN) 意味着该类型的每一行都有一个值,类型可以是 T1T2、... 或 TN,也可以是 NULL 值。

嵌套类型的顺序无关紧要:Variant(T1, T2) = Variant(T2, T1)。嵌套类型可以是任意类型,但不能是 Nullable(...)、LowCardinality(Nullable(...)) 和 Variant(...) 类型。

备注

不建议将相似类型用作变体(例如,将不同数字类型作为 Variant(UInt32, Int64),或将不同日期类型作为 Variant(Date, DateTime)),因为操作这些类型的值可能导致歧义。默认情况下,创建此类 Variant 类型将导致异常,但可以通过设置 allow_suspicious_variant_types 启用。

创建 Variant

在表列定义中使用 Variant 类型:

使用普通列进行 CAST:

当参数没有共同类型时,使用函数 if/multiIf(必须启用设置 use_variant_as_common_type):

如果数组元素/映射值没有共同类型,可以使用函数 'array/map'(必须启用设置 use_variant_as_common_type):

以子列形式读取 Variant 嵌套类型

Variant 类型支持通过类型名称作为子列从 Variant 列中读取单个嵌套类型。因此,如果你有列 variant Variant(T1, T2, T3),可以使用语法 variant.T2 读取类型为 T2 的子列,如果 T2 可以被包裹在 Nullable 中,则此子列的类型为 Nullable(T2),否则为 T2。此子列将与原始 Variant 列大小相同,并且在原始 Variant 列没有类型 T2 的所有行中将包含 NULL 值(或者如果 T2 不能被包裹在 Nullable 中,则为空值)。

Variant 子列还可以通过函数 variantElement(variant_column, type_name) 读取。

示例:

要知道每一行存储了什么变体,可以使用函数 variantType(variant_column)。它返回每行的变体类型名称的 Enum(如果行是 NULL 则返回 'None')。

示例:

Variant 列与其他列的转换

可以对 Variant 类型的列执行 4 种可能的转换。

将字符串列转换为 Variant 列

StringVariant 的转换是通过从字符串值解析出 Variant 类型的值进行的:

要禁用从 StringVariant 的转换解析,可以禁用设置 cast_string_to_dynamic_use_inference

将普通列转换为 Variant 列

可以将类型为 T 的普通列转换为包含该类型的 Variant 列:

注意:从 String 类型的转换始终通过解析执行,如果你需要将 String 列转换为不进行解析的 VariantString 变体,可以执行如下操作:

将 Variant 列转换为普通列

可以将 Variant 列转换为普通列。在这种情况下,所有嵌套变体将被转换为目标类型:

将 Variant 转换为另一个 Variant

可以将 Variant 列转换为另一个 Variant 列,但前提是目标 Variant 列包含原始 Variant 的所有嵌套类型:

从数据中读取 Variant 类型

所有文本格式(TSV、CSV、CustomSeparated、Values、JSONEachRow 等)均支持读取 Variant 类型。在数据解析期间,ClickHouse 尝试将值插入最合适的变体类型。

示例:

比较 Variant 类型的值

Variant 类型的值只能与相同 Variant 类型的值进行比较。

操作符 < 对于具有基础类型 T1 的值 v1 和具有基础类型 T2 的值 v2Variant(..., T1, ... T2, ...) 类型的定义如下:

  • 如果 T1 = T2 = T,则结果为 v1.T < v2.T(将比较基础值)。
  • 如果 T1 != T2,则结果为 T1 < T2(将比较类型名称)。

示例:

如果需要找到具有特定 Variant 值的行,可以执行以下操作:

  • 将值转换为对应的 Variant 类型:
  • Variant 子列与所需类型进行比较:

有时可以通过检查变体类型来提供额外的检查,因为不能将复杂类型如 Array/Map/Tuple 的子列放在 Nullable 中,并且在具有不同类型的行上将替代为默认值而不是 NULL

注意: 不同数值类型的变体值被视为不同变体,且不彼此比较,而是比较它们的类型名称。

示例:

注意 默认情况下,不允许在 GROUP BY/ORDER BY 键中使用 Variant 类型,如果你想使用它,请考虑其特殊比较规则并启用 allow_suspicious_types_in_group_by/allow_suspicious_types_in_order_by 设置。

与 Variant 的 JSONExtract 函数

所有 JSONExtract* 函数支持 Variant 类型: