SQL Data Types Explained

Numeric, string, date and boolean types across the major dialects, and how to pick the type that stops bad data at the door.

Concept

A column type is a constraint you get for free. It decides what can be stored, how values sort, how much space a row uses and which functions apply. Choosing types carelessly is the cheapest way to create years of data cleaning work.

Numeric types

TypeUse forNotes
SMALLINT, INT, BIGINTCounts, ids, quantitiesExact. INT stops near 2.1 billion; ids on busy tables want BIGINT.
DECIMAL(p,s) / NUMERIC(p,s)Money, rates, anything auditedExact to the declared scale. DECIMAL(10,2) holds up to 99,999,999.99.
FLOAT, REAL, DOUBLEScientific measurementsApproximate. Never use for money.

String types

TypeUse forNotes
CHAR(n)Fixed width codesPadded to n. Good for a 2 letter country code, bad for names.
VARCHAR(n)Almost all textVariable length up to n.
TEXT / CLOBLong free textOften excluded from indexes and some comparisons.

Date, time and boolean

TypeHolds
DATECalendar date, no time
TIMETime of day
TIMESTAMP / DATETIMEDate and time; TIMESTAMP WITH TIME ZONE where offsets matter
BOOLEANTrue or false. MySQL stores it as TINYINT(1); SQL Server has no BOOLEAN and uses BIT.

Syntax

CREATE TABLE orders (
    id           BIGINT        NOT NULL,
    customer_id  INT           NOT NULL,
    order_date   DATE          NOT NULL,
    placed_at    TIMESTAMP     NOT NULL,
    status       VARCHAR(12)   NOT NULL,
    total        DECIMAL(10,2) NOT NULL,
    is_gift      BOOLEAN       NOT NULL DEFAULT FALSE,
    note         TEXT          NULL
);

Example

Why approximate types are wrong for money:

-- Exact
SELECT CAST(0.1 AS DECIMAL(10,2)) + CAST(0.2 AS DECIMAL(10,2)) AS exact_sum;
-- 0.30

-- Approximate, in every language that uses binary floating point
SELECT 0.1E0 + 0.2E0 AS float_sum;
-- 0.30000000000000004

Explanation

DECIMAL stores digits, so 0.1 is exactly 0.1. FLOAT stores a binary approximation, and the tiny error compounds across a million invoice lines until a reconciliation report is off by a few paise. Storage is cheap; a failed audit is not.

Important rules

  • Use DECIMAL for money, always.
  • Store dates in date types, never as strings. '31/01/2024' sorts before '01/02/2023' as text.
  • Size VARCHAR to a real business limit, not to the biggest number you can imagine.
  • Store timestamps in UTC and convert at the edge, unless the business genuinely needs local wall clock time.

Common mistakes

  • VARCHAR for phone numbers is correct; INT for phone numbers is not - leading zeros and plus signs disappear.
  • Using FLOAT for prices and then chasing rounding differences.
  • Declaring everything VARCHAR(255) out of habit.
  • Mixing DATETIME and TIMESTAMP in MySQL without knowing that only TIMESTAMP converts by session time zone.

Best practices

  • Pick the narrowest type that comfortably fits the domain, then leave headroom on ids.
  • Keep the same type for the same concept across tables, so joins never need a cast.
  • Prefer CHECK constraints or lookup tables to a free text status column.

Practice

  1. Choose a type for each: invoice total, ISO country code, product description, order placed instant, number of items in stock, flag for subscribed to newsletter.
  2. Explain why employees.dept_id and departments.id should share a type.
  3. What breaks if a birth date is stored as VARCHAR(10)? Name two queries that become hard.

Useful resources

Hand picked references for this topic
Written by Lorens Mishra

Default administrator account created by the installer.

Continue reading

All SQL notes →

Discussion

0 comments
Sign in to join the discussion.

No comments yet. Be the first to say something.