Data Types
Prerequisites: Relational databases: tables, rows, and keys
Every column has a data type that decides what it can store. Choosing the right types keeps data valid and queries fast.
Common types
| Kind of data | Standard / PostgreSQL | MySQL | SQLite |
|---|---|---|---|
| Whole numbers | INTEGER, BIGINT |
INT, BIGINT |
INTEGER |
| Exact decimals (money) | NUMERIC(10,2) |
DECIMAL(10,2) |
NUMERIC |
| Approximate decimals | REAL, DOUBLE PRECISION |
FLOAT, DOUBLE |
REAL |
| Short text | VARCHAR(100), TEXT |
VARCHAR(100) |
TEXT |
| True / false | BOOLEAN |
BOOLEAN (stored as TINYINT) |
INTEGER 0/1 |
| Date | DATE |
DATE |
TEXT 'YYYY-MM-DD' |
| Date and time | TIMESTAMP, TIMESTAMPTZ |
DATETIME, TIMESTAMP |
TEXT ISO 8601 |
Money: use exact decimals
Approximate types (REAL, FLOAT) can't represent many decimal values
exactly:
SELECT 0.1 + 0.2 AS approximate, 0.1 + 0.2 = 0.3 AS is_equal;
+---------------------+----------+
| approximate | is_equal |
+---------------------+----------+
| 0.30000000000000004 | 0 |
+---------------------+----------+
0.1 + 0.2 isn't exactly 0.3 in floating-point arithmetic. For money,
use NUMERIC(p, s) (called DECIMAL in MySQL) in PostgreSQL, MySQL, and
SQL Server, which stores exact decimal values — or store whole cents as
integers.
(Booleans in SQLite are just 1 and 0, which is why is_equal shows
0.)
SQLite is flexible about types
Most databases reject a value of the wrong type. SQLite, by default, uses type affinity: it tries to convert values, and otherwise stores them as given:
-- standalone
CREATE TABLE t (n INTEGER);
INSERT INTO t VALUES (42), ('17'), ('hello');
SELECT n, typeof(n) AS stored_as FROM t;
+-------+-----------+
| n | stored_as |
+-------+-----------+
| 42 | integer |
| 17 | integer |
| hello | text |
+-------+-----------+
PostgreSQL would reject 'hello' in an INTEGER column with an error.
SQLite's STRICT tables (CREATE TABLE t (...) STRICT;) enforce types
too. (The -- standalone comment is just this course's marker for
examples that start from an empty database.)
Converting types: CAST
SELECT CAST('42' AS INTEGER) + 1 AS number, CAST(7 AS REAL) / 2 AS decimal;
+--------+---------+
| number | decimal |
+--------+---------+
| 43 | 3.5 |
+--------+---------+
PostgreSQL also has a shorthand: '42'::integer.
Choosing types
- Use the most specific type:
DATEfor dates (not text),INTEGERfor counts,NUMERICfor money,BOOLEANfor yes/no. - Store dates and times in ISO format (
YYYY-MM-DD HH:MM:SS), and timestamps in UTC.