Phase 0 · Start here: databases, tables and SQL · Topic 0.4

Data types: numbers, text, dates and true/false

Should know

Every column has a data type — such as INTEGER, a decimal number, TEXT, a date or a boolean — which decides what values it can hold and how they compare, sort and calculate.

Not started

Step 1 Understand it

Why you need it. The same value acts differently by type. The text '10' sorts before '9', because text compares letter by letter. Integer 7 divided by integer 2 gives 3, not 3.5. Knowing the types explains a whole class of "why is my answer wrong?" bugs.

New words in this topic (tap one to see what it means)

Watch it happen

AnimationTypes decide how values divide, compare and sort
Read the animation as text
  1. Every column has a type, and the type decides how values calculate. Two whole numbers (INTEGER) first.
  2. An integer divided by an integer gives an integer: 3. The .5 is simply thrown away — not rounded.
  3. Make one side a decimal and you get the exact answer: 7 / 2.0 = 3.5. CAST(7 AS REAL) / 2 does the same.
  4. CAST changes a value's type: the text '42' becomes the number 42, so + 1 gives 43.

Picture it

flowchart TD
  V["A value"] --> N["Number<br/>INTEGER, DECIMAL, REAL"]
  V --> T["Text<br/>TEXT, VARCHAR"]
  V --> D["Date and time<br/>DATE, TIMESTAMP"]
  V --> B["True or false<br/>BOOLEAN"]
  N --> N1["add, divide, SUM, AVG"]
  T --> T1["join, cut, LIKE"]
  D --> D1["compare, count days"]
  B --> B1["WHERE conditions"]
The type decides what you can do with a value. Numbers calculate, text and matches patterns, dates compare and count days, and true/false values drive .

The idea

Common types: for whole numbers (counts, ids), or NUMERIC for exact money values, or FLOAT for approximate numbers, or VARCHAR for words, and TIMESTAMP for dates and times, and for true or false. You can convert between types with . is not a type: it is the marker for "no value", and any can hold it unless it is declared .

The shape of it

sql
CAST(value AS INTEGER)
CAST(value AS REAL)
CAST(value AS TEXT)

Words in lower case are the parts you fill in.

How it works, step by step

  1. An integer divided by an integer gives an integer: 7 / 2 is 3. The part after the point is thrown away.
  2. Make one side a decimal and you get the exact answer: 7 / 2.0 or CAST(7 AS REAL) / 2 is 3.5.
  3. Text compares character by character, so '10' < '9' as text. Store numbers in number columns.
  4. Dates written as YYYY-MM-DD text sort correctly, because the biggest unit (year) comes first.
  5. A boolean such as salary > 60000 is true or false — or unknown when salary is NULL.

Analogy

Containers in a kitchen. A measuring jug (a number column) lets you add and divide; a label maker (text) lets you join and cut words; a calendar (dates) lets you count days. Put the right thing in the right container, or the tools stop working properly.

Where the analogy breaks

In a kitchen, a jug simply refuses a label. is relaxed and lets almost any value into any column, while rejects the wrong type outright. Don't lean on SQLite's flexibility — write as if every were strict.

Worked examples

, and how to avoid it

sql
SELECT 7 / 2 AS whole_division,
       7 / 2.0 AS exact_division,
       CAST('42' AS INTEGER) + 1 AS text_to_number;

1 row

whole_divisionexact_divisiontext_to_number
33.543

This bites in interviews when you compute a percentage: delivered / total gives 0. Multiply by 100.0 first.

Dates as YYYY-MM-DD text compare correctly

sql
SELECT name, hire_date
FROM employees
WHERE hire_date >= '2022-01-01'
ORDER BY hire_date;

3 rows

namehire_date
Eli2022-07-01
Hana2022-11-30
Gus2023-04-03

Text in single quotes is a ; the works because the year comes first.

Must-know points

  • INTEGER ÷ INTEGER = INTEGER in SQLite, PostgreSQL and . Use 100.0 or CAST to get decimals.
  • Use DECIMAL or NUMERIC for money: REAL and FLOAT are approximate and can show 0.30000000000000004.
  • Text values go in single quotes: 'London'. Double quotes are for names of or columns.
  • Store dates in date columns (or YYYY-MM-DD text), never as '06/01/2024', which sorts wrongly.
  • NULL means "no value" and can appear in any column that isn't NOT NULL.

Common mistakes

  • Computing a ratio with two integers and getting 0.
  • Storing numbers as text and getting '10' sorted before '9'.
  • Using double quotes for text values. In PostgreSQL, "London" means a column called London.

In other databases

  • is the odd one out: 7 / 2 returns 3.5000, and DIV does whole division.
  • SQLite has no real DATE or BOOLEAN type: dates are text and true/false are 1 and 0. PostgreSQL has DATE, TIMESTAMP and BOOLEAN types.
  • VARCHAR(50) caps text at 50 characters in PostgreSQL, MySQL and SQL Server; SQLite ignores the limit.

Step 2 Go further (free, optional)

Optional. The notes above are written to be enough on their own. These free resources give a second explanation and more practice.

Step 3 Practise

Try each one yourself first: out loud, or written and run in the practice box below, which saves every query you run. Then open the answer and compare.

  1. ExplainSay what it does and when to use it, in plain words, with no notes.

    Explain why 7 / 2 gives 3, and two ways to get 3.5.

    Show answer

    7 and 2 are both whole numbers (integers), and integer divided by integer gives an integer: the part after the point is thrown away, so 7 / 2 is 3. It is not rounded; it is cut off.

    Two ways to get 3.5:
    • Make one side a decimal: 7 / 2.0 or 7 * 1.0 / 2.
    • Convert it: CAST(7 AS REAL) / 2.

    The same trap hits averages and percentages built by dividing two integer columns.

  2. Writefrom a blank page, then run it

    Write a that returns each employee's name and their salary divided by 12, as an exact decimal monthly figure.

    Show answer

    Divide by 12.0, not 12. One decimal side is enough to make the whole division exact. (To show pounds and pence, wrap it in ROUND(salary / 12.0, 2), from the built-in functions lesson.)

    sql
    SELECT name, salary, salary / 12.0 AS monthly
    FROM employees
    ORDER BY emp_id;

    8 rows

    namesalarymonthly
    Asha950007916.67
    Ben700005833.33
    Chen700005833.33
    Dara600005000
    Eli450003750
    Fatima520004333.33
    Gus380003166.67
    Hana800006666.67
  3. Predictsay it before you run it

    What does SELECT 1 / 3, 1.0 / 3, '5' < '40'; return? Say all three before running it.

    Show answer

    0, then 0.333…, then 0 (false).

    • 1 / 3: two integers, so the fraction is cut off: 0.
    • 1.0 / 3: one decimal, so the answer is exact: 0.3333333333333333.
    • '5' < '40': these are text, so they compare letter by letter, like words in a dictionary. The first characters are 5 and 4, and 5 comes after 4, so '5' is bigger. The answer is false, which SQLite shows as 0.

    sql
    SELECT 1 / 3, 1.0 / 3, '5' < '40';

    1 row

    1 / 31.0 / 3'5' < '40'
    00.330
  4. Edge casesSay what happens with NULLs, ties, duplicates or no rows at all, and fix it.

    A column stores prices as text: '9', '10', '100'. What does on it return, and how do you fix it?

    Show answer

    Sorting text compares character by character, so you get '10', '100', '9'. The 1s come before the 9.

    The quick fix is to sort by the number: ORDER BY CAST(price AS INTEGER). The real fix is to store prices in a number column (INTEGER, or DECIMAL for pence), so they sort, compare and add up correctly everywhere.

    Below, just makes a tiny three- table to test on (you meet it in Phase 4). Change the ORDER BY to plain price to see the wrong order.

    sql
    WITH prices(price) AS (VALUES ('9'), ('10'), ('100'))
    SELECT price
    FROM prices
    ORDER BY CAST(price AS INTEGER);

    3 rows

    price
    9
    10
    100

Practice box: write and run your answers here

Ctrl/⌘ + Enter runs it. Select part of the query to run only that part.

Step 4 Interview-ready, then prove it

Your interview answer

About 20 to 40 seconds, said out loud.

decide how values compare and calculate. The classic traps are integer division — 7 / 2 is 3 in most databases, so for percentages I multiply by 100.0 first — and storing numbers or dates as text, which makes them sort wrongly. For money I use DECIMAL rather than FLOAT, because floating point can't represent most decimals exactly.

Follow-up questions

CHAR or VARCHAR?

CHAR(n) is fixed length and pads with spaces; VARCHAR(n) stores only what you give it, up to n. VARCHAR is the usual choice.

Why not FLOAT for money?

Floating point stores numbers in binary, so 0.1 + 0.2 is not exactly 0.3. DECIMAL stores exact decimal digits.

Tick each check when you can do it without notes

A topic is finished when you pass all four checks, not when you have read it. Be strict: if you had to look at the notes, it is not ticked yet.

  • Explain Say what it does and when to use it, in plain words, with no notes.
  • Write Write the query from a blank page, then run it to check.
  • Predict Read a query and say which rows it returns before you run it.
  • Edge cases Say what happens with NULLs, ties, duplicates or no rows at all, and fix it.

0 of 4 checks ticked.

Saved in this browser. Back it up or move it to another device.