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

PHP 列出 MySQL 所有資料庫:mysqli、PDO 與權限最佳實踐

     編輯:PHP 相關知識

早期範例使用已移除的 mysql_list_dbs()。現代 PHP 使用 mysqli 或 PDO 執行 SHOW DATABASES,並妥善處理權限、字元集、錯誤。本文提供完整實作,包含過濾系統資料庫、取得資料庫大小、建立選單/下拉選單。

方法 1:mysqli 物件導向

<?php
$mysqli = new mysqli('localhost', 'user', 'password');
if ($mysqli->connect_errno) {
    die("連線失敗 ({$mysqli->connect_errno}): {$mysqli->connect_error}");
}
$mysqli->set_charset('utf8mb4');

$result = $mysqli->query('SHOW DATABASES');
if (!$result) {
    die("查詢失敗: {$mysqli->error}");
}

$databases = [];
while ($row = $result->fetch_row()) {
    $db = $row[0];
    // 過濾系統資料庫
    if (!in_array($db, ['information_schema', 'performance_schema', 'mysql', 'sys'])) {
        $databases[] = $db;
    }
}
$result->free();
$mysqli->close();

// 輸出 HTML 選單
echo '<select name="database">';
echo '<option value="">-- 請選擇資料庫 --</option>';
foreach ($databases as $db) {
    echo '<option value="' . htmlentities($db) . '">' . htmlentities($db) . '</option>';
}
echo '</select>';
?>

方法 2:PDO(推薦,支援多種資料庫)

<?php
$dsn = 'mysql:host=localhost;charset=utf8mb4';
$options = [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_COLUMN, // 直接取得第一欄
    PDO::ATTR_EMULATE_PREPARES => false,
];

try {
    $pdo = new PDO($dsn, 'user', 'password', $options);
    $databases = $pdo->query('SHOW DATABASES')->fetchAll();

    // 過濾系統庫
    $systemDbs = ['information_schema', 'performance_schema', 'mysql', 'sys'];
    $databases = array_filter($databases, fn($db) => !in_array($db, $systemDbs));

    // 取得每個資料庫大小(選用)
    $sizes = [];
    if ($databases) {
        $placeholders = implode(',', array_fill(0, count($databases), '?'));
        $stmt = $pdo->prepare("
            SELECT table_schema, SUM(data_length + index_length) AS total_size
            FROM information_schema.tables
            WHERE table_schema IN ($placeholders)
            GROUP BY table_schema
        ");
        $stmt->execute($databases);
        foreach ($stmt->fetchAll(PDO::FETCH_KEY_PAIR) as $db => $size) {
            $sizes[$db] = $size;
        }
    }

    // 輸出
    echo '<ul>';
    foreach ($databases as $db) {
        $size = isset($sizes[$db]) ? formatBytes($sizes[$db]) : '未知';
        echo "<li>" . htmlentities($db) . " <small>($size)</small></li>";
    }
    echo '</ul>';

} catch (PDOException $e) {
    die("資料庫錯誤: {$e->getMessage()}");
}

function formatBytes(int $bytes): string
{
    $units = ['B', 'KB', 'MB', 'GB', 'TB'];
    $i = 0;
    while ($bytes >= 1024 && $i < count($units) - 1) {
        $bytes /= 1024;
        $i++;
    }
    return round($bytes, 2) . ' ' . $units[$i];
}
?>

方法 3:mysqli 取得詳細資訊(大小、編碼、建立時間)

<?php
$mysqli = new mysqli('localhost', 'user', 'password');
$mysqli->set_charset('utf8mb4');

$sql = "
    SELECT
        SCHEMA_NAME AS `database`,
        DEFAULT_CHARACTER_SET_NAME AS `charset`,
        DEFAULT_COLLATION_NAME AS `collation`,
        (SELECT SUM(data_length + index_length) FROM information_schema.tables WHERE table_schema = SCHEMA_NAME) AS `size_bytes`,
        CREATE_TIME
    FROM information_schema.SCHEMATA
    WHERE SCHEMA_NAME NOT IN ('information_schema','performance_schema','mysql','sys')
    ORDER BY SCHEMA_NAME
";

$result = $mysqli->query($sql);
$databases = $result->fetch_all(MYSQLI_ASSOC);
$result->free();

echo '<table border="1" cellpadding="6">';
echo '<tr><th>資料庫</th><th>編碼</th><th>排序規則</th><th>大小</th><th>建立時間</th></tr>';
foreach ($databases as $db) {
    echo '<tr>';
    echo '<td>' . htmlentities($db['database']) . '</td>';
    echo '<td>' . htmlentities($db['charset']) . '</td>';
    echo '<td>' . htmlentities($db['collation']) . '</td>';
    echo '<td>' . ($db['size_bytes'] ? formatBytes($db['size_bytes']) : '-') . '</td>';
    echo '<td>' . ($db['CREATE_TIME'] ? date('Y-m-d H:i:s', strtotime($db['CREATE_TIME'])) : '-') . '</td>';
    echo '</tr>';
}
echo '</table>';
?>

權限最小化原則

列出資料庫只需 SHOW DATABASES 權限。建立專用帳號:

CREATE USER 'db_lister'@'%' IDENTIFIED BY 'strong_password';
GRANT SHOW DATABASES ON *.* TO 'db_lister'@'%';
FLUSH PRIVILEGES;

若需查詢大小,額外授權:

GRANT SELECT ON information_schema.tables TO 'db_lister'@'%';

常見問題

問題解決
看不到剛建立的資料庫檢查使用者是否有該資料庫的任意權限(GRANT SELECT ON db.* TO user),MySQL 預設只顯示有權限的資料庫。
大小顯示 NULLinformation_schema.tables 統計僅含有表的資料庫,空資料庫大小為 NULL。
編碼顯示 latin1資料庫建立時未指定 CHARSET,預設 latin1。建議建立時指定 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci。
效能慢information_schema 查詢在資料庫極多(千個以上)時較慢。可快取結果、或只查 SHOW DATABASES 不 join 大小。

最佳實踐總結

  • 使用 PDO:可攜性高、例外處理統一、預設預處理語句。
  • 永遠 set_charset('utf8mb4') / DSN 加 charset=utf8mb4。
  • 過濾系統資料庫(information_schema、performance_schema、mysql、sys)。
  • 資料庫帳號遵循最小權限,僅授 SHOW DATABASES、SELECT ON information_schema.tables。
  • 結果快取(APCu/Redis),TTL 視業務而定(如 5-60 分鐘)。

掌握現代列表資料庫寫法,不僅相容 PHP 8+,更能建構安全、可維護的資料庫管理介面。

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