PostgreSQL data types define how the database stores, validates, and manipulates values in tables and expressions.
Learn the syntax, best practices, and common pitfalls when choosing and casting PostgreSQL data types.
PostgreSQL ships with numeric, character, date/time, boolean, enumerated, geometric, network, JSON, UUID, array, range, and composite data types. Each class optimizes storage and behavior for its value domain.
Supply the data type in a CREATE TABLE or ALTER TABLE statement. Add modifiers such as length, precision, NOT NULL, DEFAULT, or CHECK to tighten constraints.
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer_id UUID NOT NULL,
total NUMERIC(10,2) CHECK (total >= 0),
status TEXT DEFAULT 'new',
placed_at TIMESTAMPTZ DEFAULT now()
);
Prefer TEXT for variable-length strings without a hard limit. Use VARCHAR(n) only when a business rule requires an upper bound. Avoid CHAR(n) unless you truly need fixed-width padding.
Use the :: operator or CAST(expr AS type). Explicit casts avoid surprises and use indexes when the cast is immutable.
SELECT '42'::INT;
SELECT CAST('2024-01-01' AS DATE);
JSONB stores data in a binary format that allows indexing with GIN/GiST, equality comparison, and faster read access. JSON preserves original whitespace and ordering but lacks efficient operators.
Arrays store ordered collections of the same type: INTEGER[], TEXT[], etc. Ranges track contiguous value spans like INT4RANGE or TSRANGE. Both support containment and overlap operators.
Select the narrowest native type that supports your domain. Avoid over-allocating precision. Use UUID for distributed keys, NUMERIC for money, and TIMESTAMPTZ for timestamps.
Yesuse ALTER TABLE ... ALTER COLUMN ... TYPE. PostgreSQL rewrites the table if the cast isnt implicit, so test on large tables first.
None. Both store variable-length strings with a 1124 byte header. Only VARCHAR adds a length check.
Internally yes. PostgreSQL converts to/from the sessions time zone on input and output.