Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The Variant data type stores semi-structured, JSON-like data in a binary columnar format inside a Delta table. Instead of storing raw JSON as a STRING and parsing it at read time, store the data once as Variant and query nested fields directly by using dot and colon notation. This approach eliminates parsing overhead for each query.
Variant is a good fit for event data, application logs, API payloads, and other sources where the shape of the data varies or evolves over time.
Important
The Variant data type requires Fabric Spark runtime 2.0 (Delta 4.1) or later.
Why use Variant
Teams often store semi-structured data as a STRING column and call from_json() every time they read it. That pattern repeats parsing work on every query and requires you to define the full schema upfront.
The Variant type improves on this pattern:
- No repeated parsing — Data is parsed once on write and stored in an efficient binary format, so queries read fields directly.
- Schema-on-read — You don't need to define every field upfront. New fields appear automatically as the source data changes.
- Efficient access — The binary columnar encoding lets the engine extract individual fields without deserializing the entire value.
Create a table with a Variant column
Define a column with the VARIANT data type.
CREATE TABLE analytics.events (
event_id BIGINT,
event_time TIMESTAMP,
data VARIANT
)
Load Variant data
Use PARSE_JSON() in Spark SQL, or parse_json in PySpark and Scala, to convert a JSON string into a Variant value on write. The following example loads a nested JSON document with objects and an array.
INSERT INTO analytics.events
SELECT
1 AS event_id,
TIMESTAMP '2026-07-16 09:30:00' AS event_time,
PARSE_JSON('{
"user_id": 4471,
"action": "checkout",
"session": { "id": "a1b2c3", "duration.sec": 128 },
"items": [
{ "sku": "TShirt-01", "qty": 2, "price": 19.99 },
{ "sku": "Mug-07", "qty": 1, "price": 8.50 }
],
"beta_user": true
}') AS data
When you load from an existing column that already holds JSON text, pass that column to the same function instead of a literal string.
Query Variant fields
You can extract fields from a Variant value in two ways, and both methods are available in Spark SQL:
- Colon path notation —
data:user_idnavigates into the Variant. This syntax is shorthand for thevariant_getfunction. - The
variant_getfunction —variant_get(data, '$.user_id', 'int')takes the Variant value, a JSONPath-style path that starts with$, and a target type.
To convert an extracted value to a specific type, use the :: operator, which is shorthand for CAST(... AS type). For example, data:user_id::INT is equivalent to CAST(variant_get(data, '$.user_id') AS INT) and to variant_get(data, '$.user_id', 'int').
To escape fields with special characters, use ['<field>']. For example, data:['duration.sec'].
The following examples use colon notation in the Spark SQL tab because it's the most concise form, and the variant_get function in the PySpark and Scala tabs. In Spark SQL, you can use either form.
Access top-level fields
SELECT event_id,
data:user_id::INT AS user_id,
data:action::STRING AS action,
data:beta_user::BOOLEAN AS beta_user
FROM analytics.events
Access nested objects
Chain accessors to reach fields inside nested objects.
SELECT event_id,
data:session:id::STRING AS session_id,
data:session:duration_sec::INT AS duration_sec
FROM analytics.events
Access array elements
Use a zero-based index to access array elements. Combine it with field accessors to get values inside each element.
SELECT event_id,
data:items[0]:sku::STRING AS first_sku,
data:items[0]:qty::INT AS first_qty,
data:items[1]:price::DOUBLE AS second_price
FROM analytics.events
Filter on Variant fields
Filter and aggregate on extracted values just like regular columns.
SELECT data:action::STRING AS action,
COUNT(*) AS event_count
FROM analytics.events
WHERE data:beta_user::BOOLEAN = true
GROUP BY data:action::STRING
Handle missing or mismatched fields
Use try_variant_get when a field might be missing or hold a value that can't be cast to the requested type. Instead of failing the query, it returns NULL for those rows.
SELECT event_id,
try_variant_get(data, '$.items[1].price', 'double') AS second_price
FROM analytics.events
Inspect the shape of Variant data
Use schema_of_variant to discover the inferred structure of a Variant value, which is helpful when the source schema isn't documented.
SELECT DISTINCT schema_of_variant(data) AS inferred_schema
FROM analytics.events
Understand the protocol impact
The Variant type requires Delta reader version 3 and writer version 7. Both the reader and writer must support the Variant type table feature.
Important
Enabling the Variant type upgrades the table protocol permanently. Older readers and writers that don't support the Variant type feature can't read or write the table. Test the feature on nonproduction tables first, and verify that every engine and runtime that accesses the table supports Variant before you use it on shared tables.
You can inspect protocol-related metadata by using DESCRIBE DETAIL and by reviewing the table properties in the Delta log.
Best practices
- Use Variant for genuinely semi-structured or evolving data rather than for well-defined columns that belong in a typed schema.
- Cast extracted Variant fields to explicit types so downstream consumers get stable, predictable data types.
- Confirm that all readers and writers support the Variant type feature before you enable it on shared tables.
- Validate the feature on a nonproduction table first, because the protocol upgrade is permanent.