Every column in a SQL table has a data type, and picking the right one does more than keep your schema tidy — it determines how much storage a table uses, what values the database will actually accept, and how fast certain operations run. Getting data types right up front saves you from painful migrations later.
Exact type names vary a little between MySQL, PostgreSQL, and SQL Server, but the categories below are universal across every relational database.
Numeric Types
INT (or INTEGER) stores whole numbers and is the default choice for things like an id or a quantity. DECIMAL(precision, scale) — sometimes called NUMERIC — stores exact fixed-point numbers, which is essential for money, since floating-point types can introduce tiny rounding errors you never want in a financial calculation. FLOAT/DOUBLE trade that exactness for a much wider range, which is fine for scientific measurements but the wrong choice for currency.
CREATE TABLE products (
id INT PRIMARY KEY,
quantity INT,
price DECIMAL(10, 2) -- up to 10 digits total, 2 after the decimal point
);
Text Types
VARCHAR(n) stores variable-length text up to a maximum of n characters — the most common choice for names, emails, and short free text. CHAR(n) is fixed-length, always padding shorter values with spaces to exactly n characters; it's mostly useful for genuinely fixed-width codes like a 2-letter country code. TEXT (or CLOB) stores long-form text with no practical length limit, suited to things like a blog post body or a product description.
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(100),
country_code CHAR(2),
bio TEXT
);
Date/Time and Boolean Types
DATE stores a calendar date with no time component. DATETIME (or TIMESTAMP, depending on the database) stores both a date and a time, and TIMESTAMP columns in particular are often used for created_at/updated_at tracking since they can auto-populate on insert or update. BOOLEAN stores true/false — though some databases, like older MySQL versions, actually implement it as a tiny integer (TINYINT(1)) under the hood.
CREATE TABLE orders (
id INT PRIMARY KEY,
order_date DATE,
created_at TIMESTAMP,
is_paid BOOLEAN
);
Picking the Right Size
Choosing a type isn't just about correctness — size matters too. A VARCHAR(255) for a column that will only ever hold a 2-letter code wastes nothing at runtime (VARCHAR only stores what you actually put in it) but it does waste intent — a tighter constraint like CHAR(2) documents the expectation and lets the database reject bad data early. The same logic applies to numeric types: don't reach for a huge BIGINT on an id column that will never need to exceed a few million rows, when a regular INT covers it with less storage overhead. When you're defining a table, think about the realistic range and shape of the data, not just "whatever type is biggest and safest."
