# Choose a data type

Choose a type by its value contract: which values must fit, whether decimal digits must remain exact, and which operations the application will perform.

## Numbers

Choose an integer width that covers the full required range, including future values. Unsigned declarations reject negatives. Use Decimal for exact fixed-point amounts and Float32/Float64 for approximate measurements.

`NUMERIC` is Decimal, defaulting to `Decimal(10, 0)`. Use `LEGACY_NUMERIC` when SQLite numeric affinity is intended.

## Dates and text

Date and Date32 represent calendar days. DateTime and DateTime64 represent instants with a timezone and chosen precision. Time and Time64 represent signed seconds without a calendar date.

String stores UTF-8 text. VARCHAR(n) limits Unicode characters, while FixedString(n) requires a byte width and pads short input with zeros.

## Structured values

Use Array for an ordered list, a named Tuple for a fixed record, and Map for ordered key/value pairs. Use JSON when the document itself is the value; add typed JSON paths for fields that need a native contract.

Top-level SQL columns allow NULL unless NOT NULL is declared. Inside a typed collection, use Nullable(T) for a missing member.

## Example

```sql
CREATE TABLE products
(
    id UInt32 PRIMARY KEY,
    name VARCHAR(80) NOT NULL,
    price Decimal(18, 2),
    tags Array(String)
);
```

The declarations express different rules: identity range, text length, exact price scale and typed list members. See the [data type reference](https://coordinatordb.com/docs/reference/data-types) for limits, conversions and errors.
