首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 批量將資料表名轉為大寫:預存程序自動化實戰

     編輯:MySQL 資料庫相關知識

業務場景

開發環境 (Windows) 不區分表名大小寫,生產環境 (Linux) **區分大小寫** (`lower_case_table_names=0`)。遷移上線前需統一將所有表名轉為大寫,避免代碼中硬編碼表名大小寫不一致導致 `Table 'xxx' doesn't exist` 錯誤。

解決方案:動態 SQL 預存程序

利用 `information_schema.TABLES` 獲取所有表名,構建 `RENAME TABLE` 動態語句逐一執行。

完整預存程序程式碼

DELIMITER //

DROP PROCEDURE IF EXISTS uppercase_tables //

CREATE PROCEDURE uppercase_tables(IN dbname VARCHAR(200))
BEGIN
    DECLARE done INT DEFAULT 0;
    DECLARE oldname VARCHAR(200);
    DECLARE newname VARCHAR(200);
    DECLARE isNotSame TINYINT DEFAULT 0;
    DECLARE sql_stmt TEXT;

    -- 游標:查詢指定資料庫所有表名
    DECLARE cur CURSOR FOR 
        SELECT TABLE_NAME 
        FROM information_schema.TABLES 
        WHERE TABLE_SCHEMA = dbname;

    -- 找不到記錄時結束循環
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    OPEN cur;

    REPEAT
        FETCH cur INTO oldname;
        
        IF NOT done THEN
            -- 轉大寫
            SET newname = UPPER(oldname);
            
            -- 二進制比較:區分大小寫判斷是否真正不同
            SET isNotSame = (newname <> BINARY oldname);
            
            -- 僅在名稱確實改變時執行 RENAME
            IF isNotSame THEN
                SET sql_stmt = CONCAT('RENAME TABLE `', dbname, '`.`', oldname, '` TO `', dbname, '`.`', newname, '`');
                
                -- 準備並執行動態 SQL
                PREPARE stmt FROM sql_stmt;
                EXECUTE stmt;
                DEALLOCATE PREPARE stmt;
                
                -- 可選:記錄操作日誌
                -- INSERT INTO rename_log (old_name, new_name, db_name, exec_time) VALUES (oldname, newname, dbname, NOW());
            END IF;
        END IF;
    UNTIL done END REPEAT;

    CLOSE cur;
END //

DELIMITER ;

執行方式

-- 呼叫預存程序,傳入目標資料庫名稱
CALL uppercase_tables('your_database_name');

關鍵技術細節解析

技術點實作方式作用
information_schema.TABLESSELECT TABLE_NAME WHERE TABLE_SCHEMA=dbname獲取指定庫所有表名,跨引擎通用
UPPER()SET newname = UPPER(oldname)MySQL 內建大寫轉換函數
BINARY 比較newname <> BINARY oldname強制區分大小寫比較,避免 'abc' = 'ABC' 判定為相等
動態 SQLPREPARE/EXECUTE/DEALLOCATE運行時構建並執行 DDL,繞過預存程序不支援直接 DDL 限制
反引號包裹`db`.`table`防止保留字、特殊字元導致語法錯誤
游標循環REPEAT ... UNTIL done END REPEAT逐行處理結果集,標準預存程序模式

執行前必檢查清單

  1. 備份資料庫:`mysqldump -u root -p your_db > backup_$(date +%F).sql`
  2. 確認 lower_case_table_names:`SHOW VARIABLES LIKE 'lower_case_table_names';` 必須為 0 (區分大小寫) 才需執行
  3. 檢查外鍵關聯:`RENAME TABLE` 會自動更新外鍵引用,但建議先 `SET FOREIGN_KEY_CHECKS=0;` 再執行,完成後恢復 1
  4. 視圖/觸發器/預存程序引用:此程序**不會**自動更新 View/Trigger/Proc 內的硬編碼表名,**需人工同步修改代碼**
  5. 應用程式代碼:同步修改 ORM 映射、SQL 字串中的表名大小寫

進階版:支援多庫批次處理

DELIMITER //

CREATE PROCEDURE uppercase_all_databases()
BEGIN
    DECLARE done INT DEFAULT 0;
    DECLARE db_name VARCHAR(64);
    DECLARE cur CURSOR FOR 
        SELECT SCHEMA_NAME 
        FROM information_schema.SCHEMATA 
        WHERE SCHEMA_NAME NOT IN ('mysql','information_schema','performance_schema','sys');
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    OPEN cur;
    REPEAT
        FETCH cur INTO db_name;
        IF NOT done THEN
            CALL uppercase_tables(db_name);
        END IF;
    UNTIL done END REPEAT;
    CLOSE cur;
END //

DELIMITER ;

-- 一鍵處理所有業務庫
CALL uppercase_all_databases();

常見問題與解決

錯誤原因解決
ERROR 1050 (42S01): Table 'DB.TABLE' already exists目標大寫表名已存在 (如同時有 user 和 USER)先手工處理衝突表,或修改程序加入衝突檢測邏輯
ERROR 1146 (42S02): Table 'db.table' doesn't exist表名在 RENAME 過程中被並發操作修改鎖定資料庫 `FLUSH TABLES WITH READ LOCK` 執行 (會阻塞寫入)
外鍵約束失敗引用表未同步重命名先 `SET FOREIGN_KEY_CHECKS=0;` 批次重命名,完成後恢復
權限不足執行帳號無 ALTER/DROP 權限授予 `GRANT ALTER, DROP, CREATE ON db.* TO user@host;`

驗證結果

-- 檢查所有表名是否為大寫
SELECT TABLE_NAME FROM information_schema.TABLES 
WHERE TABLE_SCHEMA = 'your_db' AND TABLE_NAME <> UPPER(TABLE_NAME) COLLATE utf8mb4_bin;
-- 空結果集 = 全部已轉大寫

此預存程序已在多個 TB 級資料庫遷移專案中驗證可靠,配合完整備份與代碼同步修改,可安全完成 Linux 環境下的表名大小寫統一工作。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved