Skip to content

MySQL - 重命名列

随着应用程序的发展,您经常需要修改数据库模式(schema)。重命名列是一项常见任务,无论是为了提高清晰度、符合新的命名规范还是修复拼写错误。MySQL 提供了两种主要方式通过 ALTER TABLE 语句来完成此操作。

注意:重命名列需要对表拥有 ALTER 权限。

方法 1: RENAME COLUMN(简单重命名)

Section titled “方法 1: RENAME COLUMN(简单重命名)”

当您唯一的目标是更改列名而不改变其数据类型或任何其他属性时,请使用 RENAME COLUMN 子句。这是直接重命名最简单、最安全的选择。

ALTER TABLE table_name
RENAME COLUMN old_column_name TO new_column_name;

首先,我们创建一个示例 Products 表:

CREATE TABLE Products (
product_id INT PRIMARY KEY AUTO_INCREMENT,
product_name VARCHAR(255) NOT NULL,
qty INT NOT NULL
);

让我们检查其结构:

DESCRIBE Products;

输出显示了 qty 列。

字段类型空值键默认值额外
product_idintNOPRINULLauto_increment
product_namevarchar(255)NONULL
qtyintNONULL

现在,为了更清晰,我们将 qty 列重命名为 quantity_on_hand。

ALTER TABLE Products
RENAME COLUMN qty TO quantity_on_hand;

再次运行 DESCRIBE Products; 会显示更新后的列名,而数据类型和其他属性保持不变。

字段类型空值键默认值额外
product_idintNOPRINULLauto_increment
product_namevarchar(255)NONULL
quantity_on_handintNONULL

方法 2: CHANGE COLUMN(重命名和重新定义)

Section titled “方法 2: CHANGE COLUMN(重命名和重新定义)”

当您需要重命名列和/或修改其定义时,例如更改其数据类型、NULL 约束或默认值,请使用 CHANGE COLUMN 子句。

ALTER TABLE table_name
CHANGE COLUMN old_column_name new_column_name new_column_definition;

您必须提供完整的新列定义,包括数据类型和约束。如果您省略,MySQL 可能会应用一个默认定义,这可能会意外地更改您的列。

让我们向 Products 表添加一个 price 列,然后修改它。

ALTER TABLE Products ADD COLUMN price DECIMAL(8, 2);
-- 当前结构:
DESCRIBE Products;

现在,我们希望将 price 重命名为 unit_price,并增加其精度以允许更大的值。

ALTER TABLE Products
CHANGE COLUMN price unit_price DECIMAL(10, 2) NOT NULL DEFAULT 0.00;

现在描述该表会显示新名称、新数据类型、NOT NULL 约束和默认值。

字段类型空值键默认值额外
product_idintNOPRINULLauto_increment
product_namevarchar(255)NONULL
quantity_on_handintNONULL
unit_pricedecimal(10,2)NO0.00
  • 表锁定:ALTER TABLE 操作可能会锁定表,从而阻止读写。在大型表上,这可能导致显著的停机时间。MySQL/InnoDB 的现代版本已改进了在线 DDL 能力,以最大程度地减少锁定,但这仍然是一个重要的考量。
  • 应用程序影响:重命名列对您的应用程序来说是一个破坏性变更。您必须将数据库变更与更新所有列引用的代码部署进行协调。
  • 数据转换:更改数据类型(例如,从 VARCHAR(100) 到 VARCHAR(50))可能导致数据截断。始终先在预演环境(staging environment)中测试模式变更。
  • 使用迁移脚本:在专业环境中,使用 Flyway 或 Liquibase 等工具通过版本控制的迁移脚本管理所有模式变更。这可确保变更在所有环境(开发、预演、生产)中都有文档记录、经过测试且可重复。

从代码中执行 ALTER TABLE 语句非常直接。以下示例展示了如何在各种语言中安全地执行此操作。

PHP
Node.js
Java
Python
// PHP(使用 PDO 实现更与数据库无关的方法)
$host = getenv('DB_HOST') ?: 'localhost';
$db = getenv('DB_NAME') ?: 'TUTORIALS';
$user = getenv('DB_USER') ?: 'root';
$pass = getenv('DB_PASS') ?: 'password';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
echo "Connected successfully.\n";
$sql = "ALTER TABLE Products RENAME COLUMN qty TO quantity_on_hand;";
$pdo->exec($sql);
echo "Column renamed successfully!";
} catch (\PDOException $e) {
// 在生产环境中,应将此错误记录下来而不是直接输出
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
// Node.js(使用 mysql2/promise)
import mysql from 'mysql2/promise';
async function renameTableColumn() {
let connection;
try {
connection = await mysql.createConnection({
host: process.env.DB_HOST || 'localhost',
user: process.env.DB_USER || 'root',
password: process.env.DB_PASS || 'password',
database: process.env.DB_NAME || 'TUTORIALS'
});
// 注意:DDL 语句不支持表/列名的参数绑定。
// 确保这些名称经过清理,并非来自用户输入,以防止注入。
const tableName = 'Products';
const oldColName = 'qty';
const newColName = 'quantity_on_hand';
const sql = `ALTER TABLE ${tableName} RENAME COLUMN ${oldColName} TO ${newColName}`;
await connection.execute(sql);
console.log(`Column in table '${tableName}' renamed successfully.`);
} catch (error) {
console.error('Failed to rename column:', error);
} finally {
if (connection) await connection.end();
}
}
renameTableColumn();
// Java(使用 JDBC 和 try-with-resources)
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class RenameColumnExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/TUTORIALS";
String username = "root";
String password = "password";
// DDL 命令不能对标识符使用预处理语句。
// 确保表/列名来自安全来源。
String sql = "ALTER TABLE Products RENAME COLUMN qty TO quantity_on_hand";
try (Connection conn = DriverManager.getConnection(url, username, password);
Statement stmt = conn.createStatement()) {
System.out.println("Executing schema change...");
stmt.executeUpdate(sql);
System.out.println("Column renamed successfully!");
} catch (SQLException e) {
System.err.println("Database schema change failed.");
e.printStackTrace();
}
}
}
# Python(使用 mysql-connector-python)
import mysql.connector
import os
def rename_column():
connection = None
try:
connection = mysql.connector.connect(
host=os.getenv('DB_HOST', 'localhost'),
user=os.getenv('DB_USER', 'root'),
password=os.getenv('DB_PASS', 'password'),
database=os.getenv('DB_NAME', 'TUTORIALS')
)
cursor = connection.cursor()
# 警告:不要将用户输入格式化到此查询字符串中。
rename_query = "ALTER TABLE Products RENAME COLUMN qty TO quantity_on_hand"
cursor.execute(rename_query)
print("Column renamed successfully.")
except mysql.connector.Error as err:
print(f"Failed to rename column: {err}")
finally:
if connection and connection.is_connected():
cursor.close()
connection.close()
if __name__ == "__main__":
rename_column()