Перейти к основному содержимому
Перейти к основному содержимому

Variant(T1, T2, ...)

Beta feature. Learn more.

Этот тип представляет собой объединение других типов данных. Тип 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 является бета-функцией. Для его использования установите enable_variant_type = 1.

Создание 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), вы можете читать подколонку типа T2, используя синтаксис variant.T2, эта подколонка будет иметь тип Nullable(T2), если T2 может находиться внутри Nullable, а иначе будет иметь просто T2. Эта подколонка сохранит такой же размер, как и исходная колонка Variant и будет содержать значения NULL (или пустые значения, если T2 не может находиться внутри Nullable) во всех строках, в которых исходная колонка Variant не имеет тип T2.

Подколонки Variant также можно читать, используя функцию variantElement(variant_column, type_name).

Примеры:

Чтобы узнать, какой вариант хранится в каждой строке, можно использовать функцию variantType(variant_column). Она возвращает Enum с именем типа варианта для каждой строки (или 'None', если строка равна NULL).

Пример:

Преобразование между колонкой Variant и другими колонками

Существует 4 возможных преобразования, которые могут быть выполнены с колонкой типа Variant.

Преобразование колонки String в колонку Variant

Преобразование из String в Variant выполняется путем парсинга значения типа Variant из строкового значения:

Преобразование обычной колонки в колонку Variant

Возможно преобразование обычной колонки с типом T в колонку Variant, содержащую этот тип:

Примечание: Преобразование из типа String всегда выполняется через парсинг. Если вам нужно преобразовать колонку String в строковый вариант Variant без парсинга, вы можете сделать следующее:

Преобразование колонки Variant в обычную колонку

Можно преобразовать колонку Variant в обычную колонку. В этом случае все вложенные варианты будут преобразованы в целевой тип:

Преобразование Variant в другой Variant

Можно преобразовать колонку Variant в другую колонку Variant, но только если целевая колонка Variant содержит все вложенные типы из оригинального Variant:

Чтение типа Variant из данных

Все текстовые форматы (TSV, CSV, CustomSeparated, Values, JSONEachRow и т. д.) поддерживают чтение типа Variant. Во время парсинга данных ClickHouse пытается вставить значение в наиболее подходящий тип варианта.

Пример:

Сравнение значений типа Variant

Значения типа Variant могут сравниваться только с значениями одного и того же типа Variant.

Результат оператора < для значений v1, имеющего подлежащий тип T1, и v2, имеющего подлежащий тип T2, типа Variant(..., T1, ... T2, ...) определяется следующим образом:

  • Если T1 = T2 = T, результат будет v1.T < v2.T (подлежащие значения будут сравниваться).
  • Если T1 != T2, результат будет T1 < T2 (имена типов будут сравниваться).

Примеры:

Если вам нужно найти строку с определенным значением Variant, вы можете сделать одну из следующих вещей:

  • Преобразовать значение в соответствующий тип Variant:
  • Сравнить подколонку Variant с требуемым типом:

Иногда может быть полезно выполнить дополнительную проверку на тип варианта, так как подколонки с комплексными типами, такими как Array/Map/Tuple, не могут находиться внутри Nullable и будут иметь значения по умолчанию вместо NULL в строках с различными типами:

Примечание: Значения вариантов с различными числовыми типами считаются разными вариантами и не сравниваются друг с другом, их имена типов сравниваются вместо этого.

Пример:

Примечание: по умолчанию тип Variant не допускается в ключах GROUP BY/ORDER BY, если вы хотите использовать его, учтите его специальное правило сравнения и включите настройки allow_suspicious_types_in_group_by/allow_suspicious_types_in_order_by.

Функции JSONExtract с Variant

Все функции JSONExtract* поддерживают тип Variant: