YDB Types
YDB has its own type system. When passing parameters to queries you can let the SDK infer the YDB type from the Python value automatically, or declare the type explicitly when you need precise control.
Implicit Type Mapping
For most common cases, pass a plain Python value and the SDK will pick the right type:
Python value |
YDB type inferred |
Notes |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
serialised to JSON text |
|
|
serialised to JSON text |
pool.execute_with_retries(
"DECLARE $name AS Utf8; SELECT * FROM users WHERE name = $name",
parameters={"$name": "Alice"}, # str → Utf8
)
pool.execute_with_retries(
"DECLARE $active AS Bool; SELECT * FROM users WHERE active = $active",
parameters={"$active": True}, # bool → Bool
)
Explicit Types
When the automatic mapping is ambiguous or you need a type that cannot be inferred, declare the type explicitly using one of three forms.
Tuple form (value, type)
parameters={
"$id": (42, ydb.PrimitiveType.Uint64),
}
ydb.TypedValue
parameters={
"$id": ydb.TypedValue(42, ydb.PrimitiveType.Uint64),
}
Both forms are equivalent. The tuple form is more concise; TypedValue is more
explicit and works well with type checkers.
PrimitiveType Reference
Integers
Type |
Range |
Notes |
|---|---|---|
|
true / false |
|
|
−128 … 127 |
|
|
0 … 255 |
|
|
−32 768 … 32 767 |
|
|
0 … 65 535 |
|
|
−2³¹ … 2³¹−1 |
|
|
0 … 2³²−1 |
|
|
−2⁶³ … 2⁶³−1 |
default for |
|
0 … 2⁶⁴−1 |
Floating point
Type |
Notes |
|---|---|
|
32-bit IEEE 754 |
|
64-bit IEEE 754; default for Python |
Text and binary
Type |
Notes |
|---|---|
|
UTF-8 encoded text; default for Python |
|
arbitrary bytes; default for Python |
|
JSON text stored as |
|
JSON stored in a binary representation optimised for field access |
|
YSON binary/text format (YDB-specific) |
|
arbitrary-precision decimal stored as text |
Date and time
Type |
Notes |
|---|---|
|
calendar date; maps to/from |
|
date + time without timezone (second precision); maps to/from |
|
date + time without timezone (microsecond precision); maps to/from |
|
duration; maps to/from |
|
extended-range date (supports negative years); maps to/from |
|
extended-range datetime (second precision); maps to/from |
|
extended-range timestamp (microsecond precision); maps to/from |
|
extended-range interval; maps to/from |
|
date with a timezone name; maps to/from a tz-aware |
|
date + time with a timezone name (second precision); maps to/from a tz-aware |
|
date + time with a timezone name (microsecond precision); maps to/from a tz-aware |
Note
When a datetime.datetime is passed for Datetime, Datetime64,
Timestamp or Timestamp64, a tz-naive value is written as-is (its
wall-clock value), while a tz-aware value is converted to UTC first.
Integer inputs (seconds for Datetime/Datetime64, microseconds for
Timestamp/Timestamp64 since the Unix epoch) are still accepted.
Note
TzDate, TzDatetime and TzTimestamp carry an IANA timezone name.
On write, pass a tz-aware datetime.datetime whose tzinfo is a
zoneinfo.ZoneInfo — its local wall-clock and zone name are stored; any
other tzinfo raises ValueError. On read, they are returned as
tz-aware datetime.datetime values (TzDate at midnight in that zone),
or the raw "<value>,<zone>" string when the matching
with_native_*_in_result_sets option is disabled. Resolving the zone name
needs a timezone database; if it is unavailable (e.g. no tzdata
installed) reading such a value raises zoneinfo.ZoneInfoNotFoundError.
Other
Type |
Notes |
|---|---|
|
UUID stored as two 64-bit integers; maps to/from |
import datetime
import ydb
pool.execute_with_retries(
"DECLARE $ts AS Timestamp; SELECT * FROM events WHERE created_at > $ts",
parameters={
"$ts": ydb.TypedValue(
datetime.datetime(2024, 1, 1, tzinfo=datetime.timezone.utc),
ydb.PrimitiveType.Timestamp,
)
},
)
Collection Types
OptionalType
Wraps any type to allow None values. Use when a parameter or column is nullable:
# Nullable Utf8 — pass None or a string
ydb.OptionalType(ydb.PrimitiveType.Utf8)
pool.execute_with_retries(
"DECLARE $nickname AS Utf8?; "
"INSERT INTO users (id, nickname) VALUES (1, $nickname)",
parameters={"$nickname": (None, ydb.OptionalType(ydb.PrimitiveType.Utf8))},
)
ListType
A homogeneous ordered sequence:
ydb.ListType(ydb.PrimitiveType.Int64)
pool.execute_with_retries(
"DECLARE $ids AS List<Int64>; "
"SELECT * FROM users WHERE id IN $ids",
parameters={"$ids": ([1, 2, 3], ydb.ListType(ydb.PrimitiveType.Int64))},
)
DictType
A map from a key type to a value type:
# Dict<Utf8, Int64>
ydb.DictType(ydb.PrimitiveType.Utf8, ydb.PrimitiveType.Int64)
parameters={
"$scores": (
{"alice": 10, "bob": 20},
ydb.DictType(ydb.PrimitiveType.Utf8, ydb.PrimitiveType.Int64),
)
}
StructType
A named record — useful for passing rows as parameters:
row_type = (
ydb.StructType()
.add_member("id", ydb.PrimitiveType.Uint64)
.add_member("name", ydb.PrimitiveType.Utf8)
)
pool.execute_with_retries(
"DECLARE $row AS Struct<id:Uint64,name:Utf8>; "
"INSERT INTO users (id, name) VALUES ($row.id, $row.name)",
parameters={
"$row": ({"id": 1, "name": "Alice"}, row_type)
},
)
Combine ListType + StructType for bulk inserts:
row_type = (
ydb.StructType()
.add_member("id", ydb.PrimitiveType.Uint64)
.add_member("name", ydb.PrimitiveType.Utf8)
)
rows_type = ydb.ListType(row_type)
rows = [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"},
]
pool.execute_with_retries(
"DECLARE $rows AS List<Struct<id:Uint64,name:Utf8>>; "
"INSERT INTO users SELECT id, name FROM AS_TABLE($rows)",
parameters={"$rows": (rows, rows_type)},
)
TupleType
A positional (unnamed) record. Build it by chaining add_element:
point_type = (
ydb.TupleType()
.add_element(ydb.PrimitiveType.Double) # x
.add_element(ydb.PrimitiveType.Double) # y
)
parameters={"$point": ([1.0, 2.0], point_type)}
DecimalType
Fixed-precision decimal number:
# Decimal(22, 9) — 22 total digits, 9 after the decimal point (default)
ydb.DecimalType()
# Custom precision
ydb.DecimalType(precision=10, scale=2)
Reading Values from Result Sets
When you read from a result set, the SDK converts YDB values back to Python objects:
YDB type |
Python value returned |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
the inner value, or |
result_sets = pool.execute_with_retries(
"SELECT id, name, created_at, score FROM users WHERE id = 1"
)
row = result_sets[0].rows[0]
row["id"] # int
row["name"] # str (Utf8 column)
row["created_at"] # datetime.datetime (Timestamp column)
row["score"] # float (Double column)
Note
String columns return bytes, not str. If you store text in a
String column, decode it explicitly: row["col"].decode("utf-8").
Prefer Utf8 for text data.