PostgreSQL Data Types Explained for Beginners (Guide)
Confused by PostgreSQL data types? This beginner's guide explains INTEGER, VARCHAR, DATE, and BOOLEAN with simple, copy-paste SQL examples you can run today.
Confused by PostgreSQL data types? This beginner's guide explains INTEGER, VARCHAR, DATE, and BOOLEAN with simple, copy-paste SQL examples you can run today.
If you searched for "PostgreSQL data types for beginners," here is the short answer: a data type tells PostgreSQL what kind of value a column can hold, such as a whole number, some text, a date, or a true/false value. Picking the right one keeps your data clean and your database fast. In this guide, you will learn the handful of data types you actually need when you are just starting out, with small examples for each one.
A database table is made of columns, and every column stores one kind of value. A data type is the label you give a column that tells PostgreSQL, and everyone reading your table, what kind of value belongs there. For example, an "age" column should only ever hold whole numbers, so you would give it a number data type instead of a text data type.
Choosing the right data type matters for three reasons. First, it stops bad data from getting in, such as accidentally storing the word "twenty" in a column meant for numbers. Second, it saves storage space, because a number is stored more efficiently than the same value written out as text. Third, it lets PostgreSQL sort, filter, and calculate correctly, so dates sort by time and numbers sort by size instead of alphabetically.
PostgreSQL supports dozens of data types, but as a beginner you will reach for the same handful again and again. Here is a quick reference table before we go through each one in detail.
| Data type | What it stores | Example value |
|---|---|---|
| INTEGER | A whole number | 42 |
| NUMERIC(10,2) | A precise decimal number, good for money | 19.99 |
| VARCHAR(n) | Short text with a maximum length | 'hello' |
| TEXT | Text of any length | 'A long paragraph...' |
| BOOLEAN | True or false | true |
| DATE | A calendar date, no time | '2026-09-05' |
| TIMESTAMP | A date and time together | '2026-09-05 14:30:00' |
For whole numbers, like a quantity or an age, use INTEGER. If you expect very large numbers, such as a view counter that could pass two billion, use BIGINT instead. For numbers with decimal points where precision matters, like prices, use NUMERIC and tell it how many digits to keep.
CREATE TABLE products (
id INTEGER,
stock_count INTEGER,
price NUMERIC(10, 2)
);Line by line: CREATE TABLE products starts a new table named products. Each line inside the parentheses defines one column and its data type. id and stock_count are INTEGER because they only ever need whole numbers. price is NUMERIC(10, 2), which means it can store up to 10 digits total, with 2 of them after the decimal point, so it can safely hold a value like 1999.99 without rounding errors.
You could, but INTEGER is smaller and faster for the database to work with, and it makes your intent clear to anyone reading the table later. Use NUMERIC only when you truly need decimal places, such as money or measurements.
VARCHAR(n) stores text up to a maximum length you choose, such as VARCHAR(50) for a username. TEXT stores text of any length, with no limit, which makes it perfect for things like blog posts or comments. In modern PostgreSQL, TEXT and VARCHAR perform almost identically, so many beginners use TEXT everywhere and only add a VARCHAR limit when they specifically want to enforce a maximum length, like a short product code.
CREATE TABLE users (
id INTEGER,
username VARCHAR(30),
bio TEXT
);Here, username is VARCHAR(30) because usernames should stay short, and PostgreSQL will reject any value longer than 30 characters. bio is TEXT because a user's biography could be one sentence or several paragraphs, and we do not want to guess a maximum length in advance.
There is also a CHAR(n) type, which pads text with extra spaces until it reaches exactly n characters. It is rarely useful for beginners, so you can safely skip it and stick to VARCHAR and TEXT.
Use DATE when you only care about the calendar day, like a birthday. Use TIME when you only care about the clock time, like an opening hour. Use TIMESTAMP when you need both the date and the time together, like the exact moment someone placed an order.
CREATE TABLE orders (
id INTEGER,
order_date DATE,
placed_at TIMESTAMP
);order_date uses DATE because we only want to know which day the order happened, such as 2026-09-05. placed_at uses TIMESTAMP because it also records the time, such as 2026-09-05 14:30:00, which is useful if you need to know the exact order in which two orders were placed on the same day.
A BOOLEAN column can only hold one of two values: true or false. It is the right choice any time you are storing a yes-or-no fact, such as whether an account is active or whether an email has been verified.
CREATE TABLE accounts (
id INTEGER,
email VARCHAR(255),
is_active BOOLEAN
);is_active is BOOLEAN because an account is either active or it is not, with no middle option. When you insert a row, you would set this column to true or false directly, without quotes, since it is not text.
As you grow past the basics, you will run into two more common types. JSONB stores flexible, structured data, like a small object of settings that does not fit neatly into columns. UUID stores a long, unique random identifier, often used instead of a plain INTEGER for a table's id when you need IDs that are unique across many systems. You do not need either one for your first tables, but it helps to recognize them when you see them.
When in doubt, start simple. You can always change a column's data type later with an ALTER TABLE command as your app grows, so do not worry about getting it perfectly right on the first try.
Ready to put these data types to work? Learn how to build your first table step by step.
Read: How to Create a Table in PostgreSQLFor beginners, INTEGER, VARCHAR, TEXT, and TIMESTAMP cover the vast majority of columns you will create. INTEGER handles whole numbers, VARCHAR and TEXT handle text, and TIMESTAMP handles dates with times.
VARCHAR(n) enforces a maximum length, while TEXT allows text of any length. In PostgreSQL, both perform about the same, so many beginners default to TEXT unless they specifically want to limit how long a value can be.
SERIAL is a shortcut that creates an INTEGER column which automatically counts up (1, 2, 3, and so on) for every new row. As a beginner, you can use SERIAL for id columns so you do not have to generate the numbers yourself.
Yes. You can use an ALTER TABLE command to change a column's data type later, though PostgreSQL will check that your existing data can convert safely to the new type first.
Use NUMERIC with a fixed number of decimal places, such as NUMERIC(10, 2), instead of a floating-point type. NUMERIC stores exact values, which avoids the small rounding errors that can happen with money calculations.
Want a clear, guided path from your first CREATE TABLE to real queries? We can help you learn PostgreSQL the right way.
Get in touchOccasional, no-fluff notes on shipping modern software — startups, automation, Laravel, Shopify and more. No spam, unsubscribe anytime.
Keep reading
What is an index in SQL? A plain-English guide with copy-paste examples showing how indexes speed up queries and when you actually need one.
Learn JavaScript DOM manipulation for beginners: select elements, change text and styles, and handle clicks with simple, copy-paste code examples.
Let's build something
Book a free discovery call. We'll listen, ask sharp questions, and send you a proposal within 3 business days.