Variant(T1, T2, ...)
此类型表示其他数据类型的并集。类型 Variant(T1, T2, ..., TN)
意味着该类型的每一行都有一个值,类型可以是 T1
、T2
、... 或 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 列
从 String
到 Variant
的转换是通过从字符串值解析出 Variant
类型的值进行的:
要禁用从 String
到 Variant
的转换解析,可以禁用设置 cast_string_to_dynamic_use_inference
:
将普通列转换为 Variant 列
可以将类型为 T
的普通列转换为包含该类型的 Variant
列:
注意:从 String
类型的转换始终通过解析执行,如果你需要将 String
列转换为不进行解析的 Variant
的 String
变体,可以执行如下操作:
将 Variant 列转换为普通列
可以将 Variant
列转换为普通列。在这种情况下,所有嵌套变体将被转换为目标类型:
将 Variant 转换为另一个 Variant
可以将 Variant
列转换为另一个 Variant
列,但前提是目标 Variant
列包含原始 Variant
的所有嵌套类型:
从数据中读取 Variant 类型
所有文本格式(TSV、CSV、CustomSeparated、Values、JSONEachRow 等)均支持读取 Variant
类型。在数据解析期间,ClickHouse 尝试将值插入最合适的变体类型。
示例:
比较 Variant 类型的值
Variant
类型的值只能与相同 Variant
类型的值进行比较。
操作符 <
对于具有基础类型 T1
的值 v1
和具有基础类型 T2
的值 v2
的 Variant(..., 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
类型: