What's the difference between CHAR, VARCHAR, and TEXT data types?

4 minbeginnersql-basicsdata-typesvarcharchartext

Quick Answer

`CHAR(n)` is fixed-length — the engine pads shorter values with trailing spaces up to `n`, 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 n characters; 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 because rows are uniformly sized, simplifying row offset math — but this rarely matters in practice 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: TEXT has no length limit and, importantly, has no performance penalty vs VARCHAR(n) — internally they use the same storage mechanism (TOAST for large values), so PostgreSQL docs actually recommend TEXT with a CHECK constraint over VARCHAR(n) for flexibility.
  • MySQL/SQL Server: TEXT (or NVARCHAR(MAX)) historically had different storage (often off-page/BLOB-like) and couldn't always be indexed the same way as VARCHAR, or required a prefix index. This has narrowed in modern versions but still varies — check your engine's docs before assuming TEXT behaves identically to VARCHAR(MAX).

Pick VARCHAR(n) with a sensible max when there's a genuine business-rule length limit (e.g., a 100-character product name) so the constraint documents intent and catches bad data early. Use TEXT for genuinely unbounded content (article bodies, JSON blobs, 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.