Skip to content

MySQL - Change Column Type

In database management, schema evolution is a common task. You may need to change a column’s data type to accommodate new data requirements, optimize storage, or correct an initial design mistake. MySQL provides the ALTER TABLE statement for this purpose.

The ALTER TABLE Command for Column Modification

Section titled “The ALTER TABLE Command for Column Modification”

MySQL offers two primary clauses within ALTER TABLE to change a column’s definition: MODIFY and CHANGE. While they serve a similar purpose, they have a key difference.

The MODIFY clause is used to change a column’s data type and its attributes (like NULL/NOT NULL, DEFAULT, etc.) without renaming the column.

Syntax

ALTER TABLE table_name
MODIFY COLUMN column_name new_data_type [column_attributes];

Example

Let’s start with a products table where product_code was initially defined as a number, but now we need to support alphanumeric codes.

CREATE TABLE products (
product_id INT AUTO_INCREMENT PRIMARY KEY,
product_name VARCHAR(100),
product_code INT
);

Let’s view the current structure:

DESC products;

This will show the table structure:

FieldTypeNullKeyDefaultExtra
product_idintNOPRINULLauto_increment
product_namevarchar(100)YESNULL
product_codeintYESNULL

Now, we will change the product_code column from INT to VARCHAR(50) and make it mandatory (NOT NULL).

ALTER TABLE products MODIFY COLUMN product_code VARCHAR(50) NOT NULL;

Verifying the change:

DESC products;
FieldTypeNullKeyDefaultExtra
product_idintNOPRINULLauto_increment
product_namevarchar(100)YESNULL
product_codevarchar(50)NONULL

The CHANGE clause does everything MODIFY can, but it also allows you to rename the column at the same time.

Syntax

ALTER TABLE table_name
CHANGE COLUMN old_column_name new_column_name new_data_type [column_attributes];

Notice that you must specify the column name twice, even if you are not renaming it.

Example

Let’s rename product_name to item_name and increase its length to 255 characters.

ALTER TABLE products CHANGE COLUMN product_name item_name VARCHAR(255) NULL;

Verifying the change:

DESC products;
FieldTypeNullKeyDefaultExtra
product_idintNOPRINULLauto_increment
item_namevarchar(255)YESNULL
product_codevarchar(50)NONULL
  • Data Loss: Be extremely cautious when changing data types. Converting from a larger type to a smaller one (e.g., TEXT to VARCHAR(100)) can result in data truncation. Similarly, converting between incompatible types (e.g., VARCHAR with non-numeric text to INT) can lead to data loss.
  • Performance and Locking: ALTER TABLE operations can be resource-intensive, especially on large tables. Depending on the MySQL version and the specific alteration, it may lock the table, making it unavailable for reads and writes. Modern versions of MySQL have improved online DDL operations, but it’s crucial to test in a staging environment first.
  • Default Values: When changing a column’s type, MySQL may not be able to convert existing DEFAULT values. Always double-check and redefine the default value if necessary.

Executing DDL statements like ALTER TABLE from an application is common during migrations or automated setup scripts. Here are modern, best-practice examples.

Node.js
Python
Java
PHP
Using the `mysql2/promise` library for modern async/await syntax:
const sql = "ALTER TABLE products MODIFY COLUMN product_code VARCHAR(50) NOT NULL;";
await connection.execute(sql);
Using the `mysql-connector-python` library with a context manager for resource handling:
with connection.cursor() as cursor:
query = "ALTER TABLE products MODIFY COLUMN product_code VARCHAR(50) NOT NULL;"
cursor.execute(query)
connection.commit()
Using modern JDBC with a try-with-resources block to ensure resources are closed:
String sql = "ALTER TABLE products MODIFY COLUMN product_code VARCHAR(50) NOT NULL;";
try (Connection conn = ...; Statement stmt = conn.createStatement()) {
stmt.executeUpdate(sql);
}
Using PDO for a more portable and secure database access layer:
$sql = "ALTER TABLE products MODIFY COLUMN product_code VARCHAR(50) NOT NULL;";
$pdo->exec($sql);

This Python script demonstrates a safe way to connect, perform the alteration, and handle potential errors.

import mysql.connector
from mysql.connector import errorcode
# --- Configuration ---
# It's best practice to load these from environment variables or a config file
DB_CONFIG = {
'user': 'your_user',
'password': 'your_password',
'host': '127.0.0.1',
'database': 'your_database'
}
TABLE_NAME = 'products'
COLUMN_TO_MODIFY = 'product_code'
NEW_DEFINITION = 'VARCHAR(50) NOT NULL'
def modify_column_type():
"""Connects to MySQL and modifies a column's data type."""
try:
# The connection object should be managed properly
with mysql.connector.connect(**DB_CONFIG) as connection:
print("Successfully connected to the database.")
# The cursor object executes queries
with connection.cursor() as cursor:
# Prepare the ALTER TABLE statement
# Using f-strings here is safe as table/column names aren't user input
alter_query = f"ALTER TABLE {TABLE_NAME} MODIFY COLUMN {COLUMN_TO_MODIFY} {NEW_DEFINITION};"
print(f"Executing: {alter_query}")
cursor.execute(alter_query)
# A commit is needed for DDL statements to take effect
connection.commit()
print(f"Column '{COLUMN_TO_MODIFY}' in table '{TABLE_NAME}' modified successfully.")
except mysql.connector.Error as err:
if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
print("Authentication error: Check your username or password.")
elif err.errno == errorcode.ER_BAD_DB_ERROR:
print(f"Database '{DB_CONFIG['database']}' does not exist.")
else:
print(f"An error occurred: {err}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
if __name__ == "__main__":
modify_column_type()