首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 批次修改資料庫表前綴:RENAME TABLE 實作與避坑指南

     編輯:PHP 相關知識

需求場景

專案遷移、多系統共用資料庫、安全性考量(隱藏表結構),需將所有表前綴從 pre1_ 改為 pre_,或直接加上前綴。

核心方法:RENAME TABLE(原子、高效)

<?php
function renameTablePrefix(PDO $pdo, string $oldPrefix, string $newPrefix, string $database = null): array {
    $results = ['success' => [], 'failed' => []];

    // 1. 取得所有表名
    $sql = $database
        ? "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME LIKE ?"
        : "SHOW TABLES";
    $stmt = $pdo->prepare($sql);
    $database ? $stmt->execute([$database, $oldPrefix . '%']) : $stmt->execute();
    $tables = $stmt->fetchAll(PDO::FETCH_COLUMN);

    // 2. 逐一重命名
    foreach ($tables as $oldName) {
        $newName = $newPrefix . substr($oldName, strlen($oldPrefix));
        if ($oldName === $newName) continue; // 無變化略過

        try {
            // RENAME TABLE 不需權限 ALTER,只需 ALTER/DROP/CREATE 權限
            $pdo->exec("RENAME TABLE `{$oldName}` TO `{$newName}`");
            $results['success'][] = "{$oldName} → {$newName}";
        } catch (PDOException $e) {
            $results['failed'][] = "{$oldName}: " . $e->getMessage();
        }
    }
    return $results;
}

// 使用範例
$pdo = new PDO('mysql:host=localhost;dbname=myapp', 'root', 'pwd', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
$res = renameTablePrefix($pdo, 'pre1_', 'pre_');
echo "成功: " . count($res['success']) . ", 失敗: " . count($res['failed']) . "\n";
print_r($res);

進階:只加前綴(原表無前綴)

function addTablePrefix(PDO $pdo, string $prefix, string $database = null): array {
    $sql = $database
        ? "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME NOT LIKE ?"
        : "SHOW TABLES";
    $stmt = $pdo->prepare($sql);
    $database ? $stmt->execute([$database, $prefix . '%']) : $stmt->execute();
    $tables = $stmt->fetchAll(PDO::FETCH_COLUMN);

    $results = ['success' => [], 'failed' => []];
    foreach ($tables as $name) {
        $newName = $prefix . $name;
        try {
            $pdo->exec("RENAME TABLE `{$name}` TO `{$newName}`");
            $results['success'][] = "{$name} → {$newName}";
        } catch (PDOException $e) {
            $results['failed'][] = "{$name}: " . $e->getMessage();
        }
    }
    return $results;
}

關鍵注意事項(避坑指南)

風險說明對策
外鍵約束InnoDB 外鍵引用的表重命名會失敗先 SET FOREIGN_KEY_CHECKS=0,完畢後恢復 1
視圖/觸發器/存儲過程內部硬編碼表名,重命名後失效先匯出定義、重命名後重新建立,或用工具自動重寫
程式碼硬編碼表名PHP/SQL 腳本中寫死表名全專案搜尋替換、或用常數/配置檔管理表名
權限不足執行帳號無 ALTER/DROP 權限授予 GRANT ALTER, DROP, CREATE ON db.* TO user
大表鎖定時間長RENAME TABLE 會獲取元資料鎖,阻塞讀寫低峰期執行、或用 pt-online-schema-change 類工具
備份缺失操作失敗無法回滾操作前必備完整備份(mysqldump / 快照)

完整含外鍵處理版本

<?php
function safeRenamePrefix(PDO $pdo, string $oldPrefix, string $newPrefix): array {
    $pdo->exec('SET FOREIGN_KEY_CHECKS = 0');
    try {
        $res = renameTablePrefix($pdo, $oldPrefix, $newPrefix);
    } finally {
        $pdo->exec('SET FOREIGN_KEY_CHECKS = 1');
    }
    return $res;
}

替代方案:建立新表 + INSERT SELECT(零停機、大表適用)

-- 1. 建立新表結構
CREATE TABLE `pre_new_table` LIKE `pre1_old_table`;

-- 2. 複製資料(可分批、可加 WHERE)
INSERT INTO `pre_new_table` SELECT * FROM `pre1_old_table`;

-- 3. 切換(需短暫鎖定)
RENAME TABLE `pre1_old_table` TO `pre1_old_table_bak`, `pre_new_table` TO `pre_new_table`;

-- 4. 驗證無誤後刪除備份
DROP TABLE `pre1_old_table_bak`;

此法不鎖定原表寫入,適合 TB 級大表、7x24 系統。

總結

  • 小表、維護窗口期:直接 RENAME TABLE + 關閉外鍵檢查
  • 大表、無停機需求:新建表 + 分批同步 + 雙寫/切換
  • **操作前必備備份**,並在測試環境演練
  • 程式碼層面統一使用常數/配置管理表名,避免硬編碼
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved