Skip to content

Types & NULL ​

SQLite's type system is… chill. Sometimes too chill. NULL is where FE brains get hurt.

SQLite type affinity (the short version) ​

In Postgres/MySQL, columns have strict types. Put a string in an INTEGER column and you get an error (or a cast).

SQLite has type affinity - it prefers a type but will often store what you give it:

DeclaredAffinity vibe
INTEGERwhole numbers
REALfloats
TEXTstrings
BLOBbinary
NUMERICnumbers / dates-ish
sql
CREATE TABLE demo (
  id INTEGER PRIMARY KEY,
  amount REAL,
  label TEXT,
  flag INTEGER  -- often used as 0/1 boolean
);

Practical advice: still declare types. Your future self (and any ORM) will thank you. Just know SQLite won't babysit as hard as Postgres.

Booleans ​

There's no real BOOLEAN type in SQLite. People use INTEGER with 0 / 1, or sometimes TEXT. In app code, map to JS boolean.

Postgres has proper boolean. MySQL has TINYINT(1) traditions. Same idea, different costumes.

NULL is not a value ​

NULL means "unknown / missing". It is not 0, not '', not false.

sql
SELECT * FROM contacts WHERE city = NULL;      -- never matches
SELECT * FROM contacts WHERE city IS NULL;     -- correct
SELECT * FROM contacts WHERE city IS NOT NULL;

Comparisons with NULL yield "unknown", which WHERE treats as not true.

sql
-- if city is NULL, this row disappears from the result
WHERE city != 'London'

Need "not London, including missing cities"?

sql
WHERE city IS NULL OR city != 'London'
-- or
WHERE COALESCE(city, '') != 'London'

COALESCE ≈ nullish coalescing ​

sql
SELECT name, COALESCE(city, 'Unknown') AS city
FROM contacts;

FE: city ?? 'Unknown'.

Empty string vs NULL ​

CRMs love this bug.

StoredMeaning people intend
NULLwe don't know / not set
''explicitly empty

Pick a convention. I prefer NULL for "unknown" and avoid storing '' unless the product really wants a blank field. Mixing both makes filters sad.

Dates and times ​

SQLite has no dedicated date type. Common pattern: store ISO-8601 text:

sql
created_at TEXT NOT NULL DEFAULT (datetime('now'))

Or unix integers. Just be consistent.

sql
SELECT datetime('now');
SELECT date('now', '-7 days');

Postgres: timestamptz is the grown-up choice. Different syntax, same product need.

Why FE people should care ​

Your TypeScript type says companyId: number | null. The column allows NULL. The API returns null. The UI shows "-". That's one pipeline.

When someone stores 0 or '' instead of NULL, your if (contact.companyId) checks lie to you. Schema discipline prevents UI bugs. 🙌

Next: dashboard brain - Aggregates.

Notes-style SQL tutorial for front-end folks