What's the difference between CHAR, VARCHAR, and TEXT data types?
Quick Answer
CHAR(n) is fixed-length. The engine pads shorter values with trailing spaces up to n, and always uses n characters of storage. VARCHAR(n) is variable-length up to a max of n, storing only the actual content plus a small length prefix. TEXT (or VARCHAR(MAX)/unbounded VARCHAR depending on engine) stores arbitrarily long variable-length data, sometimes with different storage/indexing behavior than bounded VARCHAR.
Detailed Answer
CREATE TABLE example (
country_code CHAR(2), -- always exactly 2 chars, e.g. 'US', 'GB'
username VARCHAR(50), -- up to 50 chars, stores only what's used
biography TEXT -- arbitrarily long
);
CHAR(n) — fixed length
- Always consumes storage for exactly
ncharacters. Shorter values are right-padded with spaces (trailing spaces are typically stripped on read, depending on engine). - Best for values that are genuinely always the same length: fixed codes like ISO country codes, US state abbreviations, MD5 hex hashes.
- Slightly faster comparisons in some engines, since uniformly-sized rows simplify offset math — but this rarely matters compared to correct data modeling.
VARCHAR(n) — variable length, bounded
- Stores only the actual bytes used, plus 1–2 bytes of length prefix.
- The
(n)is a maximum, enforced at insert/update time. It's a constraint, not pre-allocated storage. - The right default for most string columns: names, emails, addresses, titles.
TEXT / unbounded — variable length, no practical cap
- PostgreSQL:
TEXThas no length limit and, importantly, has no performance penalty vsVARCHAR(n)— internally they use the same storage mechanism (TOAST for large values). PostgreSQL's own docs recommendTEXTwith aCHECKconstraint overVARCHAR(n)for flexibility. - MySQL/SQL Server:
TEXT(orNVARCHAR(MAX)) historically had different storage — often off-page/BLOB-like — and couldn't always be indexed the same way asVARCHAR, or needed a prefix index. This has narrowed in modern versions but still varies. Check your engine's docs before assumingTEXTbehaves identically toVARCHAR(MAX).
Pick VARCHAR(n) with a sensible max when there's a genuine business-rule length limit (like a 100-character product name), so the constraint documents intent and catches bad data early. Use TEXT for genuinely unbounded content like article bodies, JSON blobs, or logs. Avoid CHAR(n) unless the value truly always has that exact length — using it for a "mostly short" string wastes storage and requires careful trimming on comparison.