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

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), вы можете прочитать подколонку типа 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 и другими колонками

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

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

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

Чтобы отключить парсинг при преобразовании из String в Variant, вы можете отключить настройку cast_string_to_dynamic_use_inference:

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

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

Примечание: преобразование из типа String всегда выполняется через парсинг, если вам нужно преобразовать колонку 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: