MySQL: A Detailed Explanation and Selection Guide for MySQL…
Last updated: 2026-08-26
Data types determine how data is stored, how much space it occupies, and what operations can be performed on it—choosing the wrong type can have serious consequences.
This lesson provides a systematic overview of all MySQL data types and strategies for selecting them.
graph TB
A[MySQL Data Types] --> B[Integer Types]
A --> C[Floating-point/Fixed-point type]
A --> D[String Type]
A --> E[Date and Time Type]
A --> F[JSON Type]
B --> B1[TINYINT]
B --> B2[SMALLINT]
B --> B3[INT]
B --> B4[BIGINT]
C --> C1[FLOAT]
C --> C2[DOUBLE]
C --> C3[DECIMAL]
D --> D1[CHAR]
D --> D2[VARCHAR]
D --> D3[TEXT]
D --> D4[ENUM]
E --> E1[DATE]
E --> E2[DATETIME]
E --> E3[TIMESTAMP]
1. What You'll Learn
- Integer types (TINYINT through BIGINT)
- Floating-point and fixed-point types (FLOAT/DOUBLE/DECIMAL)
- String types (CHAR/VARCHAR/TEXT/ENUM)
- Date and time types (DATE/DATETIME/TIMESTAMP)
- JSON type (MySQL 8.0+)
2. A True Story About a Precision Issue
(1) Pain Point: The amount was calculated incorrectly
An e-commerce system stores product prices as FLOAT:
-- Demonstration of Floating-Point Precision Loss
SELECT 0.1 + 0.2; -- Results: 0.300000004(approximate value,Inaccurate)
-- It becomes more apparent after it is entered into the table
CREATE TABLE float_demo (price FLOAT);
INSERT INTO float_demo VALUES (199.99);
SELECT price FROM float_demo; -- Results: 199.99(The display is correct, but there is a slight error in the internal storage.)
SELECT price + 0.01 FROM float_demo; -- Cumulative errors may become apparent during calculations
After 1,000 transactions, the cumulative accuracy error caused a discrepancy of a few yuan in the financial reconciliation.
(2) Solution for DECIMAL
-- DECIMAL Precise Storage,No error
CREATE TABLE decimal_demo (price DECIMAL(10,2));
INSERT INTO decimal_demo VALUES (199.99);
SELECT price + 0.01 FROM decimal_demo; -- Results: 200.00(Accurate)
Result: price = 200.00, accurate with no errors.
| Type | Accuracy | Applicable Scenarios |
|---|---|---|
| FLOAT | Approximate (6–7 digits) | Scientific calculations; precision not required |
| DOUBLE | Approximate (15–16 bits) | Scientific Computing |
| DECIMAL | Precision | Amounts, financial data |
3. Integer Types
| Type | Bytes | Signed Range | Unsigned Range |
|---|---|---|---|
| TINYINT | 1 | -128 ~ 127 | 0 ~ 255 |
| SMALLINT | 2 | -32,768 ~ 32,767 | 0 ~ 65,535 |
| MEDIUMINT | 3 | -8,388,608 ~ 8,388,607 | 0 ~ 16,777,215 |
| Input | 4 | -2,147,483,648 ~ 2,147,483,647 | 0 ~ 4,294,967,295 |
| BIGINT | 8 | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 | 0 ~ 18,446,744,073,709,551,615 |
▶ Example: Integer Types
CREATE TABLE user_stats (
id INT PRIMARY KEY AUTO_INCREMENT,
age TINYINT UNSIGNED, -- Age 0-255 Enough
view_count INT UNSIGNED, -- Number of views
total_orders BIGINT UNSIGNED -- Total Number of Orders(It's very likely)
);
-- UNSIGNED Indicates unsigned(Only positive numbers)
INSERT INTO user_stats (age, view_count, total_orders)
VALUES (25, 1000000, 9999999999);
Output:
Output displayed
TINYINT for age and BIGINT for user ID.
4. Floating-Point and Fixed-Point Types
| Type | Bytes | Precision | Use Cases |
|---|---|---|---|
| FLOAT | 4 | 6–7 digits | Scientific Computing |
| DOUBLE | 8 | 15–16 bits | Scientific Computing |
| DECIMAL(M,D) | Variable | Exact | Amounts, Finance |
M = total number of digits, D = number of decimal places.
DECIMAL(10,2)indicates up to 10 integer digits + 2 decimal places.
▶ Example: Using DECIMAL
CREATE TABLE financials (
id INT PRIMARY KEY,
amount DECIMAL(12,2), -- Amount,Maximum 9999999999.99
rate DECIMAL(5,4), -- Ratio,Maximum 9.9999
quantity DECIMAL(8,0) -- Number of integers
);
INSERT INTO financials VALUES (1, 1234567.89, 0.0850, 1000);
SELECT * FROM financials;
Output:
+----+-------------+--------+----------+
| id | amount | rate | quantity |
+----+-------------+--------+----------+
| 1 | 1234567.89 | 0.0850 | 1000 |
+----+-------------+--------+----------+
5. String Type
| Type | Maximum Length | Features | Use Cases |
|---|---|---|---|
| CHAR(N) | 255 bytes | Fixed length, fast | Cell phone numbers, ID numbers, MD5 |
| VARCHAR(N) | 65,535 bytes | Variable length, space-saving | Username, email, title |
| TINYTEXT | 255 bytes | Text | Short text |
| TEXT | 65,535 bytes | Text | Article Content |
| MEDIUMTEXT | 16M | Text | Long Article |
| LONGTEXT | 4G | Text | Extra-long text |
| ENUM | 65,535 values | Enumeration | Status, Type |
| SET | 64 values | Set | Multi-select labels |
(1) CHAR vs VARCHAR
-- CHAR(10) Fixed length, storing 'abc' uses 10 bytes
-- VARCHAR(10) Variable length, storing 'abc' uses 4 bytes (3 + 1 length prefix)
CREATE TABLE phones (
-- Mobile Number (Fixed 11 digits), use CHAR for faster lookup
mobile CHAR(11),
-- Username length varies, use VARCHAR to save space
username VARCHAR(50)
);
▶ Example: ENUM Enumeration Type
CREATE TABLE orders (
id INT PRIMARY KEY,
status ENUM('pending', 'paid', 'shipped', 'completed', 'cancelled') DEFAULT 'pending'
);
INSERT INTO orders (id, status) VALUES (1, 'paid');
INSERT INTO orders (id) VALUES (2); -- Default 'pending'
-- ENUM stores numerical indexes (1,2,3...), not strings
SELECT status, status + 0 AS index_num FROM orders;
Output:
+---------+-----------+
| status | index_num |
+---------+-----------+
| paid | 2 |
| pending | 1 |
+---------+-----------+
6. Date and Time Types
| Type | Format | Range | Bytes |
|---|---|---|---|
| DATE | YYYY-MM-DD | 1000-01-01 ~ 9999-12-31 | 3 |
| TIME | HH:MM:SS | -838:59:59 ~ 838:59:59 | 3 |
| DATETIME | YYYY-MM-DD HH:MM:SS | 1000-01-01 ~ 9999-12-31 | 8 |
| TIMESTAMP | YYYY-MM-DD HH:MM:SS | 1970-01-01 ~ 2038-01-19 | 4 |
| Year | YYYY | 1901 ~ 2155 | 1 |
(1) DATETIME vs TIMESTAMP
| Dimension | DATETIME | TIMESTAMP |
|---|---|---|
| Range | 1000–9999 | 1970–2038 |
| Storage | 8 bytes | 4 bytes |
| Time Zone | Do Not Convert | Automatically Convert to UTC |
| Recommendation | Date | Record Creation/Modification Time |
▶ Example: Using Dates and Times
Output:
Query OK, 0 rows affected
Query OK, 1 row affected
---+---------+------------------
id | name | email
---+---------+------------------
1 | Alice | alice@email.com
2 | Bob | bob@email.com
3 | Charlie | charlie@email.com
---+---------+------------------
3 rows in set
CREATE TABLE events (
id INT PRIMARY KEY AUTO_INCREMENT,
event_name VARCHAR(100),
event_date DATE,
start_time TIME,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
INSERT INTO events (event_name, event_date, start_time)
VALUES ('Tech Conference', '2026-09-15', '09:00:00');
SELECT * FROM events;
Output:
+----+----------------+------------+------------+---------------------+---------------------+
| id | event_name | event_date | start_time | created_at | updated_at |
+----+----------------+------------+------------+---------------------+---------------------+
| 1 | Tech Conference| 2026-09-15 | 09:00:00 | 2026-07-03 10:00:00 | 2026-07-03 10:00:00 |
+----+----------------+------------+------------+---------------------+---------------------+
Output:
Output displayed
7. JSON Data Type (MySQL 8.0+)
▶ Example: Working with JSON
Output:
Query OK, 0 rows affected
Query OK, 1 row affected
--------+-------+--------
name | color | storage
--------+-------+--------
Alice | Red | 25
Bob | Blue | 26
Charlie | Green | 27
--------+-------+--------
3 rows in set
---+-------+----------------
id | name | email
---+-------+----------------
1 | Alice | alice@email.com
2 | Bob | bob@email.com
---+-------+----------------
2 rows in set
CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100),
attributes JSON
);
INSERT INTO products (name, attributes) VALUES
('iPhone', '{"color": "black", "storage": 128, "tags": ["phone", "apple"]}');
-- Extract JSON value
SELECT
name,
attributes->>'$.color' AS color,
attributes->>'$.storage' AS storage
FROM products;
-- JSON Array Lookup
SELECT * FROM products WHERE JSON_CONTAINS(attributes->'$.tags', '"apple"');
Output:
Output displayed
Output:
+--------+-------+---------+
| name | color | storage |
+--------+-------+---------+
| iPhone | black | 128 |
+--------+-------+---------+
8. Best Practices for Choosing Data Types
| Scenario | Recommended Type | Reason |
|---|---|---|
| Primary Key ID | BIGINT AUTO_INCREMENT | Wide range, good performance |
| Username | VARCHAR(50) | Variable length, saves space |
| VARCHAR(100) | Variable-length | |
| Phone Number | CHAR(11) | Fixed length, fast lookups |
| Password Hash | CHAR(60) | bcrypt fixed at 60 characters |
| Amount | DECIMAL(10,2) | Precise Calculation |
| Status | ENUM or TINYINT | Finite options |
| Article Content | TEXT | Long Text |
| Creation Time | TIMESTAMP | Automatically managed, 4 bytes |
| JSON Data | JSON | Supports indexes and functions |
❓ FAQ
INDEX(col(100))). If you need a full index, consider using VARCHAR.📖 Summary
- Select integer types by range: TINYINT → SMALLINT → INT → BIGINT
- Amounts must be stored as DECIMAL; FLOAT or DOUBLE cannot be used.
- CHAR fixed length (phone number), VARCHAR variable length (username)
- ENUM is suitable for a finite set of options (states, types)
- TIMESTAMP is suitable for recording time, while DATETIME is suitable for business dates
- The JSON type supports flexible, semi-structured data
📝 Exercises
-
Basic Question (Difficulty ⭐): Design the
productstable for an e-commerce system, and select the appropriate data types to store the name, price, inventory, status, and description. -
Advanced Exercise (Difficulty ⭐⭐): Create a table named
user_profilesthat contains a field namedpreferencesof type JSON, and practice extracting and querying JSON values. -
Challenge (Difficulty: ⭐⭐⭐): Compare the differences in precision between
DECIMAL(10,2)andFLOATwhen storing amounts, and use experiments to demonstrate the accuracy ofDECIMAL.