MySQL Alter Table - Modify Column
Columns sometimes need to change after a table is in use: a name that's too short, a price that needs more digits, a date stored as text, or a column that should never be empty. MySQL changes an existing column's definition with ALTER TABLE … MODIFY COLUMN (and its relatives CHANGE and ALTER COLUMN), converting the existing data as it goes.
1. Syntax
ALTER TABLE table_name
MODIFY [COLUMN] column_name new_definition [FIRST | AFTER other_column];
MODIFY replaces the whole definition. Anything you leave out (NOT NULL, DEFAULT, COMMENT, AUTO_INCREMENT) is removed. Copy the current definition from SHOW CREATE TABLE and change only what you need.2. Starting Table
DESCRIBE items;
Result: 6 rows
| Field | Type | Null | Default |
|---|---|---|---|
| item_id | int | NO | NULL |
| name | varchar(20) | YES | NULL |
| price | decimal(6,2) | YES | NULL |
| qty | smallint | YES | NULL |
| category | varchar(30) | YES | NULL |
| added_on | varchar(10) | YES | NULL |
Table: items (3 rows)
| item_id | name | price | qty | category | added_on |
|---|---|---|---|---|---|
| 1 | Desk Lamp | 899.00 | 40 | Lighting | 2026-01-05 |
| 2 | Office Chair | 4999.00 | 12 | Furniture | 2026-01-18 |
| 3 | Cable Organizer | 249.50 | 150 | NULL | 2026-02-02 |
3. Increasing a Column's Length
Item names are limited to 20 characters, which is too short:
INSERT INTO items VALUES (4, 'Ergonomic Keyboard Pro', 2499, 20, 'Accessories', '2026-02-10');
ERROR 1406 (22001): Data too long for column 'name' at row 1
ALTER TABLE items MODIFY COLUMN name VARCHAR(80);
INSERT INTO items VALUES (4, 'Ergonomic Keyboard Pro', 2499, 20, 'Accessories', '2026-02-10');
SELECT item_id, name FROM items WHERE item_id = 4;
Result: 1 row
| item_id | name |
|---|---|
| 4 | Ergonomic Keyboard Pro |
VARCHAR is an in-place, fast change as long as the length prefix stays the same size (up to 255 bytes, or above 255 bytes on both sides).4. Changing Numeric Precision
DECIMAL(6,2) can't store 10,000 or more:
UPDATE items SET price = 12999 WHERE item_id = 2;
ERROR 1264 (22003): Out of range value for column 'price' at row 1
ALTER TABLE items MODIFY price DECIMAL(10,2) NOT NULL;
UPDATE items SET price = 12999 WHERE item_id = 2;
SELECT item_id, price FROM items;
Result: 4 rows
| item_id | price |
|---|---|
| 1 | 899.00 |
| 2 | 12999.00 |
| 3 | 249.50 |
| 4 | 2499.00 |
5. Making a Column NOT NULL
Changing to NOT NULL fails while NULLs exist (in strict mode):
ALTER TABLE items MODIFY category VARCHAR(30) NOT NULL;
ERROR 1138 (22004): Invalid use of NULL value
Fill the NULLs first, then modify:
UPDATE items SET category = 'Uncategorised' WHERE category IS NULL;
ALTER TABLE items MODIFY category VARCHAR(30) NOT NULL DEFAULT 'Uncategorised';
SELECT item_id, name, category FROM items;
Result: 4 rows
| item_id | name | category |
|---|---|---|
| 1 | Desk Lamp | Lighting |
| 2 | Office Chair | Furniture |
| 3 | Cable Organizer | Uncategorised |
| 4 | Ergonomic Keyboard Pro | Accessories |
6. Converting a Data Type
The added_on column holds dates as text. Convert it to a real DATE; MySQL converts each value:
ALTER TABLE items MODIFY added_on DATE;
SELECT item_id, added_on, DAYNAME(added_on) AS weekday FROM items;
Result: 4 rows
| item_id | added_on | weekday |
|---|---|---|
| 1 | 2026-01-05 | Monday |
| 2 | 2026-01-18 | Sunday |
| 3 | 2026-02-02 | Monday |
| 4 | 2026-02-10 | Tuesday |
If any value can't be converted, the whole statement fails and the table is left unchanged:
CREATE TABLE legacy (id INT PRIMARY KEY, amount VARCHAR(10));
INSERT INTO legacy VALUES (1, '120'), (2, '75.5'), (3, 'N/A');
ALTER TABLE legacy MODIFY amount DECIMAL(8,2);
Query OK, 0 rows affected
Query OK, 3 rows affected
Records: 3 Duplicates: 0 Warnings: 0
ERROR 1366 (HY000): Incorrect DECIMAL value: '0' for column '' at row -1
Find and fix the bad rows first:
SELECT id, amount FROM legacy WHERE amount NOT REGEXP '^[0-9]+(\\.[0-9]+)?$';
UPDATE legacy SET amount = NULL WHERE id = 3;
ALTER TABLE legacy MODIFY amount DECIMAL(8,2);
SELECT * FROM legacy;
Result: 1 row
| id | amount |
|---|---|
| 3 | N/A |
Result: 3 rows
| id | amount |
|---|---|
| 1 | 120.00 |
| 2 | 75.50 |
| 3 | NULL |
7. Shrinking a Column Can Lose Data
Making a column smaller than its data is refused in strict mode, protecting you from truncation:
ALTER TABLE items MODIFY name VARCHAR(10);
ERROR 1406 (22001): Data too long for column 'name' at row 2
SELECT MAX(CHAR_LENGTH(name)) AS longest_name FROM items;
Check the longest value before shrinking
| longest_name |
|---|
| 22 |
8. Setting or Dropping a Default with ALTER COLUMN
To change only the default, ALTER COLUMN is simpler and instant:
ALTER TABLE items ALTER COLUMN qty SET DEFAULT 0;
INSERT INTO items (item_id, name, price, category) VALUES (5, 'Mouse Pad', 199, 'Accessories');
SELECT item_id, name, qty FROM items WHERE item_id = 5;
ALTER TABLE items ALTER COLUMN qty DROP DEFAULT;
Result: 1 row
| item_id | name | qty |
|---|---|---|
| 5 | Mouse Pad | 0 |
9. Moving a Column
ALTER TABLE items MODIFY category VARCHAR(30) NOT NULL DEFAULT 'Uncategorised' AFTER name;
SHOW COLUMNS FROM items;
Result: 6 rows
| Field | Type | Null | Default |
|---|---|---|---|
| item_id | int | NO | NULL |
| name | varchar(80) | YES | NULL |
| category | varchar(30) | NO | Uncategorised |
| price | decimal(10,2) | NO | NULL |
| qty | smallint | YES | NULL |
| added_on | date | YES | NULL |
10. CHANGE COLUMN: Rename and Modify Together
ALTER TABLE items CHANGE COLUMN qty stock_qty INT UNSIGNED NOT NULL DEFAULT 0;
SHOW COLUMNS FROM items LIKE 'stock%';
Result: 1 row
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| stock_qty | int unsigned | NO | 0 |
For a rename only, RENAME COLUMN is safer because you can't accidentally drop attributes; see MySQL Rename Column.
11. Several Changes in One Statement
ALTER TABLE items
MODIFY name VARCHAR(100) NOT NULL,
MODIFY price DECIMAL(12,2) NOT NULL DEFAULT 0.00;
SHOW COLUMNS FROM items WHERE Field IN ('name', 'price');
Result: 2 rows
| Field | Type | Null | Default |
|---|---|---|---|
| name | varchar(100) | NO | NULL |
| price | decimal(12,2) | NO | 0.00 |
12. Safety Tips
- Changing a type usually rebuilds the table (COPY or INPLACE). On large tables plan for time and disk space; tools such as
gh-ostorpt-online-schema-changecan help. - Run
SHOW CREATE TABLEfirst and keep every attribute you still want in the new definition. - Check the data fits:
MAX(CHAR_LENGTH(col)),MAX(col), invalid values. - Back up the table, or test on a copy (
CREATE TABLE t_test LIKE t; INSERT INTO t_test SELECT * FROM t;).
13. Summary
MODIFY COLUMNchanges a column's type, size, nullability, default or position, keeping its name.CHANGE COLUMNdoes the same and renames;ALTER COLUMNonly sets or drops the default.- Restate the full definition: omitted attributes are removed.
- Strict mode stops conversions that would truncate or invalidate data; clean the data first.
- Type changes may rebuild large tables, so plan them.