Skip to content

Commit 078e3b9

Browse files
authored
Merge pull request #561 from bytebase/o-branch-9
docs: add alter column type mysql
2 parents da35edf + bef9a47 commit 078e3b9

File tree

2 files changed

+288
-0
lines changed

2 files changed

+288
-0
lines changed

content/reference/mysql/how-to/_layout.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@
1111

1212
## [How to ALTER TABLE](/reference/mysql/how-to/how-to-alter-table-mysql)
1313

14+
## [How to ALTER COLUMN TYPE](/reference/mysql/how-to/how-to-alter-column-type-mysql)
15+
1416
## [How to ADD CONSTRAINT](/reference/mysql/how-to/how-to-add-constraint-mysql)
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
---
2+
title: How to ALTER COLUMN TYPE in MySQL
3+
updated_at: 2025/03/17 12:00:00
4+
---
5+
6+
_Official documentation: [ALTER TABLE](https://dev.mysql.com/doc/refman/8.0/en/alter-table.html)_
7+
8+
<HintBlock type="info">
9+
10+
Changing column type should be conducted with caution. Some organizations have strict approval process and even disallow altering column type at all. You can enforce [approval process](/docs/administration/custom-approval/) or [disallowing altering column type](/docs/sql-review/review-rules/#column.disallow-change-type) via Bytebase.
11+
12+
</HintBlock>
13+
14+
## Basic Syntax for Altering Column Type
15+
16+
MySQL provides two primary methods to change a column's data type:
17+
18+
```sql
19+
-- Using MODIFY
20+
ALTER TABLE table_name
21+
MODIFY COLUMN column_name new_data_type;
22+
23+
-- Using CHANGE (allows renaming the column)
24+
ALTER TABLE table_name
25+
CHANGE COLUMN old_column_name new_column_name new_data_type;
26+
```
27+
28+
## Simple Type Conversions
29+
30+
For straightforward conversions:
31+
32+
```sql
33+
-- Change an integer column to bigint
34+
ALTER TABLE orders
35+
MODIFY COLUMN order_id BIGINT;
36+
37+
-- Change a varchar column to text
38+
ALTER TABLE customers
39+
MODIFY COLUMN notes TEXT;
40+
41+
-- Change a float column to decimal with precision
42+
ALTER TABLE products
43+
MODIFY COLUMN price DECIMAL(10,2);
44+
```
45+
46+
## String Type Conversions
47+
48+
```sql
49+
-- VARCHAR to TEXT (no data loss)
50+
ALTER TABLE messages
51+
MODIFY COLUMN content TEXT;
52+
53+
-- VARCHAR to CHAR (fixed length)
54+
ALTER TABLE countries
55+
MODIFY COLUMN country_code CHAR(2);
56+
57+
-- TEXT to VARCHAR with potential truncation
58+
ALTER TABLE products
59+
MODIFY COLUMN description VARCHAR(255);
60+
```
61+
62+
## Numeric Type Conversions
63+
64+
```sql
65+
-- Integer to BIGINT (safe, no data loss)
66+
ALTER TABLE measurements
67+
MODIFY COLUMN value BIGINT;
68+
69+
-- DECIMAL to INTEGER (truncation of fractional part)
70+
ALTER TABLE products
71+
MODIFY COLUMN price INT;
72+
73+
-- FLOAT to DECIMAL (fixed precision)
74+
ALTER TABLE financial
75+
MODIFY COLUMN amount DECIMAL(15,2);
76+
```
77+
78+
## Date and Time Conversions
79+
80+
```sql
81+
-- DATETIME to DATE (drops time portion)
82+
ALTER TABLE events
83+
MODIFY COLUMN event_datetime DATE;
84+
85+
-- DATE to DATETIME
86+
ALTER TABLE appointments
87+
MODIFY COLUMN appointment_date DATETIME;
88+
89+
-- TIMESTAMP to DATETIME
90+
ALTER TABLE logs
91+
MODIFY COLUMN log_time DATETIME;
92+
93+
-- Converting string to date/time
94+
ALTER TABLE imported_events
95+
MODIFY COLUMN event_date DATE;
96+
```
97+
98+
## ENUM and SET Conversions
99+
100+
```sql
101+
-- Converting VARCHAR to ENUM
102+
ALTER TABLE tickets
103+
MODIFY COLUMN status ENUM('open', 'in_progress', 'closed', 'cancelled');
104+
105+
-- Expanding an existing ENUM
106+
ALTER TABLE products
107+
MODIFY COLUMN size ENUM('small', 'medium', 'large', 'extra-large');
108+
109+
-- Converting to SET type
110+
ALTER TABLE users
111+
MODIFY COLUMN roles SET('admin', 'editor', 'viewer');
112+
```
113+
114+
## JSON Conversions
115+
116+
MySQL 5.7+ supports JSON data type:
117+
118+
```sql
119+
-- Converting TEXT to JSON
120+
ALTER TABLE configurations
121+
MODIFY COLUMN config JSON;
122+
123+
-- Converting VARCHAR to JSON
124+
ALTER TABLE api_responses
125+
MODIFY COLUMN response JSON;
126+
```
127+
128+
## Handling Special Cases
129+
130+
### Converting with Default Values
131+
132+
```sql
133+
-- Set default value during conversion
134+
ALTER TABLE users
135+
MODIFY COLUMN status VARCHAR(20) DEFAULT 'active';
136+
137+
-- Update NULL values before conversion to NOT NULL
138+
UPDATE users SET last_login = '1970-01-01' WHERE last_login IS NULL;
139+
ALTER TABLE users
140+
MODIFY COLUMN last_login DATETIME NOT NULL;
141+
```
142+
143+
### Preserving Column Attributes
144+
145+
When modifying a column's type, you need to specify all attributes you want to keep:
146+
147+
```sql
148+
-- Before: INT NOT NULL AUTO_INCREMENT
149+
-- After: BIGINT NOT NULL AUTO_INCREMENT
150+
ALTER TABLE customers
151+
MODIFY COLUMN id BIGINT NOT NULL AUTO_INCREMENT;
152+
```
153+
154+
### Converting with Length Constraints
155+
156+
```sql
157+
-- Check potential data truncation before conversion
158+
SELECT COUNT(*) FROM products WHERE LENGTH(description) > 100;
159+
160+
-- Perform the conversion (potential data loss)
161+
ALTER TABLE products
162+
MODIFY COLUMN description VARCHAR(100);
163+
```
164+
165+
## Performance Considerations
166+
167+
### Table Locking
168+
169+
```sql
170+
-- Specify algorithm and lock for better performance
171+
ALTER TABLE large_table
172+
MODIFY COLUMN data TEXT,
173+
ALGORITHM=INPLACE, LOCK=NONE;
174+
175+
-- Not all modifications support INPLACE algorithm
176+
-- Check if your modification is supported:
177+
-- https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html
178+
```
179+
180+
### Low-Impact Approaches for Production
181+
182+
For large tables in production, a multi-step approach might be preferred:
183+
184+
```sql
185+
-- 1. Add a new column
186+
ALTER TABLE large_table ADD COLUMN new_column new_type;
187+
188+
-- 2. Update data in the new column
189+
UPDATE large_table SET new_column = old_column;
190+
191+
-- 3. (Optional) Add any constraints
192+
ALTER TABLE large_table MODIFY COLUMN new_column new_type NOT NULL;
193+
194+
-- 4. Drop the old column when ready
195+
ALTER TABLE large_table DROP COLUMN old_column;
196+
197+
-- 5. Rename the new column to the old name
198+
ALTER TABLE large_table CHANGE COLUMN new_column old_column new_type;
199+
```
200+
201+
## Common Errors and Solutions
202+
203+
See [MySQL Error Reference](/reference/mysql/error/overview/) for errors you may encounter.
204+
205+
Here are the most common errors when altering column types:
206+
207+
### Error 1265: Data truncated
208+
209+
```sql
210+
-- This happens when data doesn't fit the new type
211+
-- Identify problematic rows
212+
SELECT * FROM table_name
213+
WHERE LENGTH(column_name) > new_length;
214+
215+
-- Fix the data first, then alter the column
216+
UPDATE table_name
217+
SET column_name = SUBSTRING(column_name, 1, new_length)
218+
WHERE LENGTH(column_name) > new_length;
219+
```
220+
221+
### Error 1366: Incorrect integer value
222+
223+
```sql
224+
-- When converting string to numeric and non-numeric values exist
225+
-- Find problematic rows
226+
SELECT * FROM table_name
227+
WHERE column_name REGEXP '[^0-9]';
228+
229+
-- Clean data before conversion
230+
UPDATE table_name SET column_name = 0
231+
WHERE column_name REGEXP '[^0-9]';
232+
```
233+
234+
### Error 1292: Incorrect datetime value
235+
236+
```sql
237+
-- When converting to DATE/DATETIME with invalid format
238+
-- Find invalid dates
239+
SELECT * FROM table_name
240+
WHERE STR_TO_DATE(column_name, '%Y-%m-%d') IS NULL;
241+
242+
-- Fix dates before conversion
243+
UPDATE table_name
244+
SET column_name = '2000-01-01'
245+
WHERE STR_TO_DATE(column_name, '%Y-%m-%d') IS NULL;
246+
```
247+
248+
### Error 1118: Row size too large
249+
250+
```sql
251+
-- Happens when the new column size would make row exceed max row size
252+
-- Consider using vertical partitioning or TEXT/BLOB columns
253+
ALTER TABLE large_table
254+
MODIFY COLUMN large_column TEXT;
255+
```
256+
257+
## Data Type Conversion Compatibility
258+
259+
Not all conversions preserve data integrity. Here's a quick reference:
260+
261+
| From Type | To Type | Data Safety | Notes |
262+
| --------- | ------- | ----------- | ----------------------------------------- |
263+
| INT | BIGINT | Safe | No data loss |
264+
| BIGINT | INT | Unsafe | Potential overflow |
265+
| VARCHAR | TEXT | Safe | No data loss |
266+
| TEXT | VARCHAR | Unsafe | Potential truncation |
267+
| FLOAT | DECIMAL | Mostly Safe | Potential precision issues |
268+
| DATETIME | DATE | Unsafe | Time portion lost |
269+
| CHAR | VARCHAR | Safe | No data loss |
270+
| VARCHAR | ENUM | Unsafe | Non-matching values become empty or error |
271+
272+
## Best Practices
273+
274+
1. **Backup First**: Always back up your database before altering column types
275+
276+
2. **Test in Development**: Never make type changes directly in production first
277+
278+
3. **Check Data**: Verify data compatibility before conversion
279+
280+
4. **Transaction Safety**: Consider using transactions for related changes
281+
282+
5. **Choose Optimal Timing**: Schedule alterations during low-traffic periods
283+
284+
6. **Use ALGORITHM and LOCK**: Specify optimal algorithm when possible
285+
286+
7. **Consider Index Impact**: Be aware that indexes may need to be rebuilt

0 commit comments

Comments
 (0)