> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-3a82795f.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> ClickHouse의 Variant 데이터 타입 문서

# Variant(T1, T2, ...)

이 타입은 다른 데이터 타입의 유니언을 나타냅니다. `Variant(T1, T2, ..., TN)` 타입은 이 타입의 각 행이 `T1`, `T2`, ..., `TN` 중 하나의 타입 값을 가지거나, 어느 타입에도 해당하지 않는 `NULL` 값을 가질 수 있음을 의미합니다.

중첩된 타입의 순서는 중요하지 않습니다. 즉, Variant(T1, T2) = Variant(T2, T1)입니다.
중첩된 타입은 Nullable(...), LowCardinality(Nullable(...)), Variant(...) 타입을 제외하면 어떤 타입이든 사용할 수 있습니다.

<Note>
  유사한 타입을 variant로 사용하는 것은 권장되지 않습니다(예: `Variant(UInt32, Int64)`처럼 서로 다른 숫자 타입이나 `Variant(Date, DateTime)`처럼 서로 다른 날짜 타입).
  이러한 타입의 값을 처리할 때 모호성이 발생할 수 있기 때문입니다. 기본적으로 이런 `Variant` 타입을 생성하면 예외가 발생하지만, 설정 `allow_suspicious_variant_types`를 사용해 활성화할 수 있습니다.
</Note>

<div id="creating-variant">
  ## Variant 생성하기
</div>

테이블 컬럼 정의에서 `Variant` 타입을 사용하는 방법:

```sql theme={null}
CREATE TABLE test (v Variant(UInt64, String, Array(UInt64))) ENGINE = Memory;
INSERT INTO test VALUES (NULL), (42), ('Hello, World!'), ([1, 2, 3]);
SELECT v FROM test;
```

```text theme={null}
┌─v─────────────┐
│ ᴺᵁᴸᴸ          │
│ 42            │
│ Hello, World! │
│ [1,2,3]       │
└───────────────┘
```

일반 컬럼에서 CAST 사용:

```sql theme={null}
SELECT toTypeName(variant) AS type_name, 'Hello, World!'::Variant(UInt64, String, Array(UInt64)) as variant;
```

```text theme={null}
┌─type_name──────────────────────────────┬─variant───────┐
│ Variant(Array(UInt64), String, UInt64) │ Hello, World! │
└────────────────────────────────────────┴───────────────┘
```

인수에 공통 타입이 없을 때 `if/multiIf` 함수를 사용합니다(`use_variant_as_common_type` 설정이 활성화되어 있어야 함):

```sql theme={null}
SET use_variant_as_common_type = 1;
SELECT if(number % 2, number, range(number)) as variant FROM numbers(5);
```

```text theme={null}
┌─variant───┐
│ []        │
│ 1         │
│ [0,1]     │
│ 3         │
│ [0,1,2,3] │
└───────────┘
```

```sql theme={null}
SET use_variant_as_common_type = 1;
SELECT multiIf((number % 4) = 0, 42, (number % 4) = 1, [1, 2, 3], (number % 4) = 2, 'Hello, World!', NULL) AS variant FROM numbers(4);
```

```text theme={null}
┌─variant───────┐
│ 42            │
│ [1,2,3]       │
│ Hello, World! │
│ ᴺᵁᴸᴸ          │
└───────────────┘
```

배열 요소/맵 값에 공통 타입이 없는 경우 'array/map' 함수를 사용합니다(이 기능을 사용하려면 `use_variant_as_common_type` 설정이 활성화되어 있어야 합니다):

```sql theme={null}
SET use_variant_as_common_type = 1;
SELECT array(range(number), number, 'str_' || toString(number)) as array_of_variants FROM numbers(3);
```

```text theme={null}
┌─array_of_variants─┐
│ [[],0,'str_0']    │
│ [[0],1,'str_1']   │
│ [[0,1],2,'str_2'] │
└───────────────────┘
```

```sql theme={null}
SET use_variant_as_common_type = 1;
SELECT map('a', range(number), 'b', number, 'c', 'str_' || toString(number)) as map_of_variants FROM numbers(3);
```

```text theme={null}
┌─map_of_variants───────────────┐
│ {'a':[],'b':0,'c':'str_0'}    │
│ {'a':[0],'b':1,'c':'str_1'}   │
│ {'a':[0,1],'b':2,'c':'str_2'} │
└───────────────────────────────┘
```

<div id="reading-variant-nested-types-as-subcolumns">
  ## Variant 중첩 타입을 서브컬럼으로 읽기
</div>

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)` 함수를 사용해서도 읽을 수 있습니다.

예시:

```sql theme={null}
CREATE TABLE test (v Variant(UInt64, String, Array(UInt64))) ENGINE = Memory;
INSERT INTO test VALUES (NULL), (42), ('Hello, World!'), ([1, 2, 3]);
SELECT v, v.String, v.UInt64, v.`Array(UInt64)` FROM test;
```

```text theme={null}
┌─v─────────────┬─v.String──────┬─v.UInt64─┬─v.Array(UInt64)─┐
│ ᴺᵁᴸᴸ          │ ᴺᵁᴸᴸ          │     ᴺᵁᴸᴸ │ []              │
│ 42            │ ᴺᵁᴸᴸ          │       42 │ []              │
│ Hello, World! │ Hello, World! │     ᴺᵁᴸᴸ │ []              │
│ [1,2,3]       │ ᴺᵁᴸᴸ          │     ᴺᵁᴸᴸ │ [1,2,3]         │
└───────────────┴───────────────┴──────────┴─────────────────┘
```

```sql theme={null}
SELECT toTypeName(v.String), toTypeName(v.UInt64), toTypeName(v.`Array(UInt64)`) FROM test LIMIT 1;
```

```text theme={null}
┌─toTypeName(v.String)─┬─toTypeName(v.UInt64)─┬─toTypeName(v.Array(UInt64))─┐
│ Nullable(String)     │ Nullable(UInt64)     │ Array(UInt64)               │
└──────────────────────┴──────────────────────┴─────────────────────────────┘
```

```sql theme={null}
SELECT v, variantElement(v, 'String'), variantElement(v, 'UInt64'), variantElement(v, 'Array(UInt64)') FROM test;
```

```text theme={null}
┌─v─────────────┬─variantElement(v, 'String')─┬─variantElement(v, 'UInt64')─┬─variantElement(v, 'Array(UInt64)')─┐
│ ᴺᵁᴸᴸ          │ ᴺᵁᴸᴸ                        │                        ᴺᵁᴸᴸ │ []                                 │
│ 42            │ ᴺᵁᴸᴸ                        │                          42 │ []                                 │
│ Hello, World! │ Hello, World!               │                        ᴺᵁᴸᴸ │ []                                 │
│ [1,2,3]       │ ᴺᵁᴸᴸ                        │                        ᴺᵁᴸᴸ │ [1,2,3]                            │
└───────────────┴─────────────────────────────┴─────────────────────────────┴────────────────────────────────────┘
```

각 행에 저장된 variant를 확인하려면 `variantType(variant_column)` 함수를 사용할 수 있습니다. 이 함수는 각 행의 variant 유형 이름을 나타내는 `Enum`을 반환합니다(`NULL`인 행은 `'None'`).

예시:

```sql theme={null}
CREATE TABLE test (v Variant(UInt64, String, Array(UInt64))) ENGINE = Memory;
INSERT INTO test VALUES (NULL), (42), ('Hello, World!'), ([1, 2, 3]);
SELECT variantType(v) FROM test;
```

```text theme={null}
┌─variantType(v)─┐
│ None           │
│ UInt64         │
│ String         │
│ Array(UInt64)  │
└────────────────┘
```

```sql theme={null}
SELECT toTypeName(variantType(v)) FROM test LIMIT 1;
```

```text theme={null}
┌─toTypeName(variantType(v))──────────────────────────────────────────┐
│ Enum8('None' = -1, 'Array(UInt64)' = 0, 'String' = 1, 'UInt64' = 2) │
└─────────────────────────────────────────────────────────────────────┘
```

<div id="conversion-between-a-variant-column-and-other-columns">
  ## Variant 컬럼과 다른 컬럼 사이의 변환
</div>

`Variant` 타입의 컬럼에 대해 수행할 수 있는 변환은 4가지입니다.

<div id="converting-a-string-column-to-a-variant-column">
  ### String 컬럼을 Variant 컬럼으로 변환하기
</div>

`String`에서 `Variant`로의 변환은 문자열 값을 파싱해 `Variant` 타입의 값을 추출하는 방식으로 수행됩니다:

```sql theme={null}
SELECT '42'::Variant(String, UInt64) AS variant, variantType(variant) AS variant_type
```

```text theme={null}
┌─variant─┬─variant_type─┐
│ 42      │ UInt64       │
└─────────┴──────────────┘
```

```sql theme={null}
SELECT '[1, 2, 3]'::Variant(String, Array(UInt64)) as variant, variantType(variant) as variant_type
```

```text theme={null}
┌─variant─┬─variant_type──┐
│ [1,2,3] │ Array(UInt64) │
└─────────┴───────────────┘
```

````sql theme={null}
SELECT CAST(map('key1', '42', 'key2', 'true', 'key3', '2020-01-01'), 'Map(String, Variant(UInt64, Bool, Date))') AS map_of_variants, mapApply((k, v) -> (k, variantType(v)), map_of_variants) AS map_of_variant_types```
````

```text theme={null}
┌─map_of_variants─────────────────────────────┬─map_of_variant_types──────────────────────────┐
│ {'key1':42,'key2':true,'key3':'2020-01-01'} │ {'key1':'UInt64','key2':'Bool','key3':'Date'} │
└─────────────────────────────────────────────┴───────────────────────────────────────────────┘
```

`String`에서 `Variant`로 변환할 때 파싱을 비활성화하려면 `cast_string_to_dynamic_use_inference` 설정을 비활성화하면 됩니다:

```sql theme={null}
SET cast_string_to_variant_use_inference = 0;
SELECT '[1, 2, 3]'::Variant(String, Array(UInt64)) as variant, variantType(variant) as variant_type
```

```text theme={null}
┌─variant───┬─variant_type─┐
│ [1, 2, 3] │ String       │
└───────────┴──────────────┘
```

<div id="converting-an-ordinary-column-to-a-variant-column">
  ### 일반 컬럼을 Variant 컬럼으로 변환하기
</div>

타입이 `T`인 일반 컬럼은 해당 타입을 포함하는 `Variant` 컬럼으로 변환할 수 있습니다:

```sql theme={null}
SELECT toTypeName(variant) AS type_name, [1,2,3]::Array(UInt64)::Variant(UInt64, String, Array(UInt64)) as variant, variantType(variant) as variant_name
```

```text theme={null}
┌─type_name──────────────────────────────┬─variant─┬─variant_name──┐
│ Variant(Array(UInt64), String, UInt64) │ [1,2,3] │ Array(UInt64) │
└────────────────────────────────────────┴─────────┴───────────────┘
```

참고: `String` 타입에서의 변환은 항상 파싱을 거쳐 수행됩니다. 파싱 없이 `String` 컬럼을 `Variant`의 `String` 대안으로 변환해야 하는 경우, 다음과 같이 할 수 있습니다:

```sql theme={null}
SELECT '[1, 2, 3]'::Variant(String)::Variant(String, Array(UInt64), UInt64) as variant, variantType(variant) as variant_type
```

```sql theme={null}
┌─variant───┬─variant_type─┐
│ [1, 2, 3] │ String       │
└───────────┴──────────────┘
```

<div id="converting-a-variant-column-to-an-ordinary-column">
  ### Variant 컬럼을 일반 컬럼으로 변환하기
</div>

`Variant` 컬럼은 일반 컬럼으로 변환할 수 있습니다. 이 경우 모든 중첩된 variant가 대상 타입으로 변환됩니다:

```sql theme={null}
CREATE TABLE test (v Variant(UInt64, String)) ENGINE = Memory;
INSERT INTO test VALUES (NULL), (42), ('42.42');
SELECT v::Nullable(Float64) FROM test;
```

```text theme={null}
┌─CAST(v, 'Nullable(Float64)')─┐
│                         ᴺᵁᴸᴸ │
│                           42 │
│                        42.42 │
└──────────────────────────────┘
```

<div id="converting-a-variant-to-another-variant">
  ### Variant를 다른 Variant로 변환하기
</div>

`Variant` 컬럼은 다른 `Variant` 컬럼으로 변환할 수 있지만, 대상 `Variant` 컬럼에 원래 `Variant`의 모든 중첩 타입이 포함된 경우에만 가능합니다:

```sql theme={null}
CREATE TABLE test (v Variant(UInt64, String)) ENGINE = Memory;
INSERT INTO test VALUES (NULL), (42), ('String');
SELECT v::Variant(UInt64, String, Array(UInt64)) FROM test;
```

```text theme={null}
┌─CAST(v, 'Variant(UInt64, String, Array(UInt64))')─┐
│ ᴺᵁᴸᴸ                                              │
│ 42                                                │
│ String                                            │
└───────────────────────────────────────────────────┘
```

<div id="reading-variant-type-from-the-data">
  ## 데이터에서 Variant 타입 읽기
</div>

모든 텍스트 형식(TSV, CSV, CustomSeparated, Values, JSONEachRow 등)에서 `Variant` 타입을 읽을 수 있습니다. 데이터를 파싱하는 동안 ClickHouse는 값을 가장 적합한 Variant 타입으로 삽입하려고 시도합니다.

예시:

```sql theme={null}
SELECT
    v,
    variantElement(v, 'String') AS str,
    variantElement(v, 'UInt64') AS num,
    variantElement(v, 'Float64') AS float,
    variantElement(v, 'DateTime') AS date,
    variantElement(v, 'Array(UInt64)') AS arr
FROM format(JSONEachRow, 'v Variant(String, UInt64, Float64, DateTime, Array(UInt64))', $$
{"v" : "Hello, World!"},
{"v" : 42},
{"v" : 42.42},
{"v" : "2020-01-01 00:00:00"},
{"v" : [1, 2, 3]}
$$)
```

```text theme={null}
┌─v───────────────────┬─str───────────┬──num─┬─float─┬────────────────date─┬─arr─────┐
│ Hello, World!       │ Hello, World! │ ᴺᵁᴸᴸ │  ᴺᵁᴸᴸ │                ᴺᵁᴸᴸ │ []      │
│ 42                  │ ᴺᵁᴸᴸ          │   42 │  ᴺᵁᴸᴸ │                ᴺᵁᴸᴸ │ []      │
│ 42.42               │ ᴺᵁᴸᴸ          │ ᴺᵁᴸᴸ │ 42.42 │                ᴺᵁᴸᴸ │ []      │
│ 2020-01-01 00:00:00 │ ᴺᵁᴸᴸ          │ ᴺᵁᴸᴸ │  ᴺᵁᴸᴸ │ 2020-01-01 00:00:00 │ []      │
│ [1,2,3]             │ ᴺᵁᴸᴸ          │ ᴺᵁᴸᴸ │  ᴺᵁᴸᴸ │                ᴺᵁᴸᴸ │ [1,2,3] │
└─────────────────────┴───────────────┴──────┴───────┴─────────────────────┴─────────┘
```

<div id="comparing-values-of-variant-data">
  ## Variant 타입 값 비교
</div>

`Variant` 타입의 값은 동일한 `Variant` 타입의 값과만 비교할 수 있습니다.

기본적으로 비교 연산자는 [Variant의 기본 구현](#functions-with-variant-arguments)을 사용하여
각 variant type에 대해 개별적으로 비교를 수행합니다. 이는 setting `use_variant_default_implementation_for_comparisons = 0`을 사용해 비활성화할 수 있으며,
이 경우 아래에 설명된 네이티브 Variant 비교 규칙이 사용됩니다. **참고:** `ORDER BY`는 항상 네이티브 비교를 사용합니다.

**네이티브 Variant 비교 규칙:**

타입 `Variant(..., T1, ... T2, ...)`에서 내부 타입이 `T1`인 값 `v1`과 내부 타입이 `T2`인 값 `v2`에 대한 연산자 `<`의 결과는 다음과 같이 정의됩니다.

* `T1 = T2 = T`이면 결과는 `v1.T < v2.T`입니다(내부 값이 비교됩니다).
* `T1 != T2`이면 결과는 `T1 < T2`입니다(타입 이름이 비교됩니다).

예시:

```sql theme={null}
SET allow_suspicious_types_in_order_by = 1;
CREATE TABLE test (v1 Variant(String, UInt64, Array(UInt32)), v2 Variant(String, UInt64, Array(UInt32))) ENGINE=Memory;
INSERT INTO test VALUES (42, 42), (42, 43), (42, 'abc'), (42, [1, 2, 3]), (42, []), (42, NULL);
```

```sql theme={null}
SELECT v2, variantType(v2) AS v2_type FROM test ORDER BY v2;
```

```text theme={null}
┌─v2──────┬─v2_type───────┐
│ []      │ Array(UInt32) │
│ [1,2,3] │ Array(UInt32) │
│ abc     │ String        │
│ 42      │ UInt64        │
│ 43      │ UInt64        │
│ ᴺᵁᴸᴸ    │ None          │
└─────────┴───────────────┘
```

```sql theme={null}
SELECT v1, variantType(v1) AS v1_type, v2, variantType(v2) AS v2_type, v1 = v2, v1 < v2, v1 > v2 FROM test;
```

```text theme={null}
┌─v1─┬─v1_type─┬─v2──────┬─v2_type───────┬─equals(v1, v2)─┬─less(v1, v2)─┬─greater(v1, v2)─┐
│ 42 │ UInt64  │ 42      │ UInt64        │              1 │            0 │               0 │
│ 42 │ UInt64  │ 43      │ UInt64        │              0 │            1 │               0 │
│ 42 │ UInt64  │ abc     │ String        │              0 │            0 │               1 │
│ 42 │ UInt64  │ [1,2,3] │ Array(UInt32) │              0 │            0 │               1 │
│ 42 │ UInt64  │ []      │ Array(UInt32) │              0 │            0 │               1 │
│ 42 │ UInt64  │ ᴺᵁᴸᴸ    │ None          │              0 │            1 │               0 │
└────┴─────────┴─────────┴───────────────┴────────────────┴──────────────┴─────────────────┘

```

특정 `Variant` 값을 가진 행을 찾아야 한다면, 다음 방법 중 하나를 사용할 수 있습니다:

* 값을 해당 `Variant` 유형으로 CAST합니다:

```sql theme={null}
SELECT * FROM test WHERE v2 == [1,2,3]::Array(UInt32)::Variant(String, UInt64, Array(UInt32));
```

```text theme={null}
┌─v1─┬─v2──────┐
│ 42 │ [1,2,3] │
└────┴─────────┘
```

* `Variant` 서브컬럼을 필요한 타입과 비교합니다:

```sql theme={null}
SELECT * FROM test WHERE v2.`Array(UInt32)` == [1,2,3] -- 또는 variantElement(v2, 'Array(UInt32)') 사용
```

```text theme={null}
┌─v1─┬─v2──────┐
│ 42 │ [1,2,3] │
└────┴─────────┘
```

`Array/Map/Tuple` 같은 복합 타입의 서브컬럼은 `Nullable` 안에 포함될 수 없으며, 타입이 다른 행에서는 `NULL` 대신 기본값을 가지므로, 경우에 따라 variant 타입에 추가 검사를 수행하는 것이 유용할 수 있습니다:

```sql theme={null}
SELECT v2, v2.`Array(UInt32)`, variantType(v2) FROM test WHERE v2.`Array(UInt32)` == [];
```

```text theme={null}
┌─v2───┬─v2.Array(UInt32)─┬─variantType(v2)─┐
│ 42   │ []               │ UInt64          │
│ 43   │ []               │ UInt64          │
│ abc  │ []               │ String          │
│ []   │ []               │ Array(UInt32)   │
│ ᴺᵁᴸᴸ │ []               │ None            │
└──────┴──────────────────┴─────────────────┘
```

```sql theme={null}
SELECT v2, v2.`Array(UInt32)`, variantType(v2) FROM test WHERE variantType(v2) == 'Array(UInt32)' AND v2.`Array(UInt32)` == [];
```

```text theme={null}
┌─v2─┬─v2.Array(UInt32)─┬─variantType(v2)─┐
│ [] │ []               │ Array(UInt32)   │
└────┴──────────────────┴─────────────────┘
```

**참고:** 숫자 타입이 서로 다른 Variant 값은 서로 다른 Variant로 간주되며, 서로 비교하지 않고 대신 타입 이름을 비교합니다.

예시:

```sql theme={null}
SET allow_suspicious_variant_types = 1;
CREATE TABLE test (v Variant(UInt32, Int64)) ENGINE=Memory;
INSERT INTO test VALUES (1::UInt32), (1::Int64), (100::UInt32), (100::Int64);
SELECT v, variantType(v) FROM test ORDER by v;
```

```text theme={null}
┌─v───┬─variantType(v)─┐
│ 1   │ Int64          │
│ 100 │ Int64          │
│ 1   │ UInt32         │
│ 100 │ UInt32         │
└─────┴────────────────┘
```

**참고** 기본적으로 `Variant` 타입은 `GROUP BY`/`ORDER BY` 키로 사용할 수 없습니다. 사용하려면 이 타입의 특수한 비교 규칙을 고려하고 `allow_suspicious_types_in_group_by`/`allow_suspicious_types_in_order_by` 설정을 활성화하십시오.

<div id="jsonextract-functions-with-variant">
  ## Variant를 지원하는 JSONExtract 함수
</div>

모든 `JSONExtract*` 함수는 `Variant` 타입을 지원합니다.

```sql theme={null}
SELECT JSONExtract('{"a" : [1, 2, 3]}', 'a', 'Variant(UInt32, String, Array(UInt32))') AS variant, variantType(variant) AS variant_type;
```

```text theme={null}
┌─variant─┬─variant_type──┐
│ [1,2,3] │ Array(UInt32) │
└─────────┴───────────────┘
```

```sql theme={null}
SELECT JSONExtract('{"obj" : {"a" : 42, "b" : "Hello", "c" : [1,2,3]}}', 'obj', 'Map(String, Variant(UInt32, String, Array(UInt32)))') AS map_of_variants, mapApply((k, v) -> (k, variantType(v)), map_of_variants) AS map_of_variant_types
```

```text theme={null}
┌─map_of_variants──────────────────┬─map_of_variant_types────────────────────────────┐
│ {'a':42,'b':'Hello','c':[1,2,3]} │ {'a':'UInt32','b':'String','c':'Array(UInt32)'} │
└──────────────────────────────────┴─────────────────────────────────────────────────┘
```

```sql theme={null}
SELECT JSONExtractKeysAndValues('{"a" : 42, "b" : "Hello", "c" : [1,2,3]}', 'Variant(UInt32, String, Array(UInt32))') AS variants, arrayMap(x -> (x.1, variantType(x.2)), variants) AS variant_types
```

```text theme={null}
┌─variants───────────────────────────────┬─variant_types─────────────────────────────────────────┐
│ [('a',42),('b','Hello'),('c',[1,2,3])] │ [('a','UInt32'),('b','String'),('c','Array(UInt32)')] │
└────────────────────────────────────────┴───────────────────────────────────────────────────────┘
```

<div id="functions-with-variant-arguments">
  ## Variant 인수를 사용하는 함수
</div>

ClickHouse의 대부분의 함수는 **Variant에 대한 기본 구현**을 통해 `Variant` 타입 인수를 자동으로 지원합니다.
`26.1` 버전부터는 Variant 타입을 명시적으로 처리하지 않는 함수에 Variant 컬럼이 전달되면 ClickHouse는 다음을 수행합니다:

1. Variant 컬럼에서 각 변형 타입을 추출합니다
2. 각 변형 타입에 대해 함수를 개별적으로 실행합니다
3. 결과 타입에 따라 결과를 적절히 결합합니다

따라서 별도의 특별한 처리 없이도 일반 함수를 Variant 컬럼에 사용할 수 있습니다.

**예시:**

```sql theme={null}
CREATE TABLE test (v Variant(UInt32, String)) ENGINE = Memory;
INSERT INTO test VALUES (42), ('hello'), (NULL);
SELECT *, toTypeName(v) FROM test WHERE v = 42;
```

```text theme={null}
   ┌─v──┬─toTypeName(v)───────────┐
1. │ 42 │ Variant(String, UInt32) │
   └────┴─────────────────────────┘
```

비교 연산자는 각 variant 타입에 자동으로 개별 적용되므로 Variant 컬럼을 필터링할 수 있습니다.

**결과 타입 동작:**

결과 타입은 함수가 각 variant에 대해 반환하는 값에 따라 달라집니다.

* **서로 다른 결과 타입**: `Variant(T1, T2, ...)`

  ```sql theme={null}
  CREATE TABLE test2 (v Variant(UInt64, Float64)) ENGINE = Memory;
  INSERT INTO test2 VALUES (42::UInt64), (42.42);
  SELECT v + 1 AS result, toTypeName(result) FROM test2;
  ```

  ```text theme={null}
  ┌─result─┬─toTypeName(plus(v, 1))──┐
  │     43 │ Variant(Float64, UInt64) │
  │  43.42 │ Variant(Float64, UInt64) │
  └────────┴─────────────────────────┘
  ```

* **타입 비호환성**: 호환되지 않는 variant에는 `NULL`

  ```sql theme={null}
  CREATE TABLE test3 (v Variant(Array(UInt32), UInt32)) ENGINE = Memory;
  INSERT INTO test3 VALUES ([1,2,3]), (42);
  SELECT v + 10 AS result, toTypeName(result) FROM test3;
  ```

  ```text theme={null}
  ┌─result─┬─toTypeName(plus(v, 10))─┐
  │   ᴺᵁᴸᴸ │ Nullable(UInt64)        │
  │     52 │ Nullable(UInt64)        │
  └────────┴─────────────────────────┘
  ```

<Note>
  **오류 처리:** 함수가 variant 타입을 처리할 수 없을 때는 타입 관련 오류(ILLEGAL\_TYPE\_OF\_ARGUMENT,
  TYPE\_MISMATCH, CANNOT\_CONVERT\_TYPE, NO\_COMMON\_TYPE)만 포착되며, 해당 행의 결과는 NULL이 됩니다. 그 밖의 오류(예:
  0으로 나누기, 메모리 부족)는 실제 문제를 조용히 숨기지 않도록 평소처럼 그대로 발생합니다.
</Note>

<div id="variant-type-mismatch-behavior">
  ### 유형 불일치 시 동작
</div>

설정 `variant_throw_on_type_mismatch`는 함수가 `Variant` 컬럼에 적용될 때, 행에 실제로 저장된 유형이 해당 함수와 호환되지 않으면 어떻게 처리할지를 제어합니다:

* `true` (기본값) — 처음으로 호환되지 않는 행에서 예외(`ILLEGAL_TYPE_OF_ARGUMENT`)를 발생시킵니다.
* `false` — 호환되지 않는 행에는 `NULL`을 반환하고, 호환되는 행은 결과를 유지합니다.

**예시:**

```sql theme={null}
CREATE TABLE test (v Variant(String, UInt64)) ENGINE = Memory;
INSERT INTO test VALUES ('hello'), (42), ('foo');

-- 기본값 (불일치 시 예외 발생): length()는 UInt64를 허용하지 않으므로 쿼리에서 예외가 발생합니다.
SELECT length(v) FROM test;  -- ILLEGAL_TYPE_OF_ARGUMENT 예외 발생

-- throw 비활성화 시: 호환되지 않는 행은 NULL을 반환합니다.
SET variant_throw_on_type_mismatch = false;
SELECT v, length(v) FROM test ORDER BY v::String NULLS LAST;
```

```text theme={null}
┌─v─────┬─length(v)─┐
│ foo   │         3 │
│ hello │         5 │
│ 42    │      ᴺᵁᴸᴸ │
└───────┴───────────┘
```
