Posted by Kyle Hankinson July 8, 2024
Every database has multiple string types, and choosing the wrong one can waste storage, break character support, or limit query performance.
PostgreSQL makes it simple — use TEXT for almost everything:
| Type | Max Length | Notes |
|---|---|---|
TEXT |
Unlimited | Preferred general-purpose type |
VARCHAR(n) |
n characters | Same performance as TEXT |
CHAR(n) |
Fixed n characters | Pads with spaces, rarely useful |
There is no performance difference between TEXT and VARCHAR(n) in PostgreSQL. VARCHAR(n) only adds a length check constraint. The PostgreSQL documentation recommends TEXT or VARCHAR without a length limit.
CREATE TABLE users (
name TEXT NOT NULL,
email TEXT NOT NULL
);
MySQL's string types differ in storage and maximum length:
| Type | Max Length | Storage |
|---|---|---|
TINYTEXT |
255 bytes | Length + 1 byte |
TEXT |
65,535 bytes | Length + 2 bytes |
MEDIUMTEXT |
16 MB | Length + 3 bytes |
LONGTEXT |
4 GB | Length + 4 bytes |
VARCHAR(n) |
65,535 bytes (row limit) | Length + 1-2 bytes |
CHAR(n) |
255 characters | Fixed n bytes |
Key difference: VARCHAR columns can be fully indexed, but TEXT columns can only be indexed with a prefix length:
-- Works
CREATE INDEX idx_email ON users (email(255));
-- Does not work (no prefix)
-- CREATE INDEX idx_email ON users (email); -- Error if email is TEXT
For columns you will index or use in WHERE clauses, prefer VARCHAR(n). For large content (blog posts, descriptions), use TEXT or MEDIUMTEXT.
SQL Server's big distinction is Unicode support:
| Type | Max Length | Character Set |
|---|---|---|
VARCHAR(n) |
8,000 bytes | Non-Unicode (1 byte/char) |
VARCHAR(MAX) |
2 GB | Non-Unicode |
NVARCHAR(n) |
4,000 characters | Unicode (2 bytes/char) |
NVARCHAR(MAX) |
2 GB | Unicode |
CHAR(n) |
8,000 bytes | Fixed, non-Unicode |
NCHAR(n) |
4,000 characters | Fixed, Unicode |
TEXT |
2 GB | Deprecated — use VARCHAR(MAX) |
Use NVARCHAR if your data may contain non-English characters (names, addresses, user-generated content). Use VARCHAR only when you are certain the data is ASCII-only and storage is a concern.
-- Good default
CREATE TABLE users (
name NVARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL -- emails are ASCII
);
| Type | Max Length | Notes |
|---|---|---|
VARCHAR2(n) |
4,000 bytes (or 32,767 with MAX_STRING_SIZE) | Standard string type |
NVARCHAR2(n) |
4,000 bytes | Unicode variant |
CHAR(n) |
2,000 bytes | Fixed length |
CLOB |
4 GB | For large text |
Always use VARCHAR2, not VARCHAR. Oracle's documentation states that VARCHAR may behave differently in future versions. VARCHAR2 is the guaranteed type.
CREATE TABLE users (
name VARCHAR2(100) NOT NULL,
bio CLOB
);
| Scenario | MySQL | PostgreSQL | SQL Server | Oracle |
|---|---|---|---|---|
| Short strings (names, emails) | VARCHAR(n) |
TEXT |
NVARCHAR(n) |
VARCHAR2(n) |
| Long content (articles, bios) | TEXT or MEDIUMTEXT |
TEXT |
NVARCHAR(MAX) |
CLOB |
| ASCII-only data | VARCHAR(n) |
TEXT |
VARCHAR(n) |
VARCHAR2(n) |
| Unicode data | VARCHAR(n) with utf8mb4 |
TEXT (always UTF-8) |
NVARCHAR(n) |
NVARCHAR2(n) |
Using CHAR for variable-length data: CHAR(50) pads shorter values with spaces, wasting storage and causing comparison surprises.
VARCHAR(255) by default: Many ORMs default to 255, but there is no magic about this number (it was the max for MySQL's old TINYTEXT). Choose a length that reflects your actual data constraints.
Ignoring character sets in MySQL: VARCHAR(100) with latin1 holds 100 bytes. With utf8mb4, a character can be up to 4 bytes, so the row size limit is reached sooner.
About the author — Kyle Hankinson is the founder and sole developer of SQLPro Studio and the Hankinsoft Development suite of database tools. He has been building native macOS and iOS applications since 2010.
Try SQLPro Studio — A powerful database manager for MySQL, PostgreSQL, Microsoft SQL Server, SQLite, Oracle, and Snowflake. Available on macOS, iOS, and Windows.
Download Free Trial View Pricing Compare