Data Types
Why every column has a type, the handful of types you will use constantly, and how types quietly protect your data from nonsense.
Every column in a relational table has a data type — a declared kind of value it is allowed to hold. This page demystifies types so they feel like a helpful guardrail rather than a hurdle.
Why types exist
A type answers the question "what kind of value goes here?" and
then the database enforces that answer. Declare a column as a
number, and the database will refuse the text "banana". Declare it
as a date, and "someday" is rejected.
This is the database doing one of its five core jobs from earlier: protecting your data by refusing invalid values at the moment they are entered, before they can pollute reports and break logic.
The types you will actually use
There are many types, but a small handful covers the vast majority of real work. Meet them:
| Type (PostgreSQL) | Holds | Examples |
|---|---|---|
INTEGER | Whole numbers | 0, 42, -7 |
NUMERIC | Exact decimal numbers (great for money) | 19.99, 0.05 |
TEXT | Text of any length | 'Ada', 'hello world' |
BOOLEAN | True/false values | true, false |
DATE | A calendar date | '2026-03-14' |
TIMESTAMP | A date and time | '2026-03-14 09:30:00' |
A note on money
Use NUMERIC for money, never a floating-point type. NUMERIC
stores decimals exactly, so 0.10 + 0.20 is exactly 0.30.
Floating-point types can introduce tiny rounding errors that are
unacceptable when counting cents.
Types shape what operations make sense
A column's type does not just restrict storage — it also decides what you can do with the values:
- You can do arithmetic on
INTEGERandNUMERIC(price * 2). - You can compare and concatenate
TEXT('Ms. ' || name). - You can compare and subtract
DATEs to get a number of days. - You can filter
BOOLEANcolumns directly (WHERE is_active).
Choosing the right type up front means the natural operations are available and the nonsensical ones (like multiplying two names) are impossible.
See types accept and reject values
The first query stores well-typed values happily. Then try the commented-out line to watch the type system reject nonsense.
Notice you could compute price * 2 because price is a number.
You could not do that with the name column — and that is the
type system quietly steering you toward correct, meaningful queries.
Check your understanding
What is the main job of a column's data type?
To decide the column's position in the table.
To declare what kind of value the column holds and let the database reject values that don't fit.
To automatically translate values into other languages.
To make the column appear bold when displayed.
Which PostgreSQL type is the best choice for storing a price like 19.99?
INTEGER, because prices are basically numbers.
TEXT, so you can store the dollar sign too.
NUMERIC, because it stores exact decimal values, which is important for money.
BOOLEAN, because a price is either present or not.
You declare a column as DATE and try to insert the value 'someday'. What happens, and why is that good?
It is stored as-is, because databases accept any text.
The whole table is deleted to protect it.
The database rejects the value because it is not a valid date, catching the error early.
It is silently converted to today's date.