CREATE TABLE prices (amount numeric(12,2) NOT NULL);
3. Using Serial Types
Type
Underlying
Status
smallserial
smallint + sequence
LEGACY
serial
integer + sequence
LEGACY
bigserial
bigint + sequence
LEGACY
Note: Prefer GENERATED ALWAYS AS IDENTITY — SQL-standard and avoids permission quirks.
4. Using Character Types
Type
Notes
text
Unlimited length (preferred)
varchar(n)
Max n chars; no perf benefit vs text
char(n)
Blank-padded fixed (avoid)
citext
Case-insensitive (extension)
5. Using Boolean Type
Literal
Maps To
TRUE
't', 'true', 'yes', 'on', '1'
FALSE
'f', 'false', 'no', 'off', '0'
NULL
unknown
6. Using Date and Time Types
Type
Size
Notes
date
4 B
Calendar day
time [(p)]
8 B
Time of day, no TZ
timetz
12 B
Avoid; no DST awareness
timestamp
8 B
Without timezone
timestamptz
8 B
Stored UTC; recommended
7. Using INTERVAL Type
SELECT INTERVAL '1 year 2 months 3 days 04:05:06';SELECT now() + INTERVAL '30 days';SELECT EXTRACT(EPOCH FROM INTERVAL '1 day'); -- 86400
Field
Example
Months
INTERVAL '3 months'
Days
INTERVAL '7 days'
Microseconds
INTERVAL '0.5 seconds'
8. Using UUID Type
CREATE EXTENSION IF NOT EXISTS pgcrypto;SELECT gen_random_uuid(); -- v4-- PG 18+ has gen_uuid_v7() for time-ordered UUIDs
Source
Function
pgcrypto
gen_random_uuid()
uuid-ossp
uuid_generate_v1mc(), uuid_generate_v4()
9. Using JSON Types
Type
Storage
Use
json
Verbatim text
Preserve formatting; rarely needed
jsonb
Binary, indexed
Default choice
CREATE TABLE events ( id bigserial PRIMARY KEY, payload jsonb NOT NULL);CREATE INDEX events_payload_gin ON events USING gin (payload jsonb_path_ops);
10. Using Array Types
CREATE TABLE posts ( id bigserial PRIMARY KEY, tags text[] NOT NULL DEFAULT '{}');INSERT INTO posts(tags) VALUES (ARRAY['sql','postgres','tips']);SELECT * FROM posts WHERE 'sql' = ANY(tags);CREATE INDEX posts_tags_gin ON posts USING gin(tags);
11. Using ENUM Types
CREATE TYPE order_status AS ENUM ('new','paid','shipped','cancelled');ALTER TABLE orders ALTER COLUMN status TYPE order_status USING status::order_status;ALTER TYPE order_status ADD VALUE 'refunded' AFTER 'cancelled';
Op
Notes
ADD VALUE
Cannot run inside transaction block before PG 12
Sort order
Definition order, not alphabetical
Rename
ALTER TYPE ... RENAME VALUE 'a' TO 'b'
12. Using Composite Types
CREATE TYPE address AS (street text, city text, zip text);CREATE TABLE people (id bigserial PRIMARY KEY, home address);INSERT INTO people(home) VALUES (ROW('1 Main','Boston','02110'));SELECT (home).city FROM people;
13. Using Domain Types
CREATE DOMAIN email_addr AS text CHECK (VALUE ~* '^[^@]+@[^@]+\.[^@]+
Benefit
Detail
Reuse
Apply same CHECK to many columns
Centralize
Change rule in one place
14. Using Range Types
Type
Element
int4range / int8range
integer / bigint
numrange
numeric
tsrange / tstzrange
timestamp / timestamptz
daterange
date
CREATE TABLE reservations ( room_id int NOT NULL, during tstzrange NOT NULL, EXCLUDE USING gist (room_id WITH =, during WITH &&));