核心差異一覽
| 函數 | 返回結構 | 存取方式 | 記憶體佔用 |
mysqli_fetch_row() | 數值索引陣列 [0]=>值, [1]=>值... | $row[0], $row[1] | 較低 (僅值) |
mysqli_fetch_array() | 雙模式:數值索引 + 關聯索引 | $row[0] 或 $row['欄位名'] | 較高 (鍵值對) |
mysqli_fetch_assoc() | 純關聯索引 ['欄位名']=>值 | $row['欄位名'] | 中等 |
mysqli_fetch_array() 參數控制模式
$row = mysqli_fetch_array($result, MYSQLI_ASSOC); // 僅關聯索引 (同 fetch_assoc)
$row = mysqli_fetch_array($result, MYSQLI_NUM); // 僅數值索引 (同 fetch_row)
$row = mysqli_fetch_array($result, MYSQLI_BOTH); // 預設:雙模式
代碼對比實戰
mysqli_fetch_row() - 僅數值索引
<?php
$mysqli = new mysqli("localhost", "root", "", "test", 3306);
if ($mysqli->connect_errno) { die("Connect failed: " . $mysqli->connect_error); }
$result = $mysqli->query("SELECT id, name, detail FROM userinfo");
while ($row = $result->fetch_row()) { // 僅數值索引
echo "<tr>";
echo "<td>" . htmlspecialchars($row[0]) . "</td>"; // id
echo "<td>" . htmlspecialchars($row[1]) . "</td>"; // name
echo "<td>" . htmlspecialchars($row[2]) . "</td>"; // detail
echo "</tr>";
}
$result->free();
$mysqli->close();
?>
mysqli_fetch_array(MYSQLI_ASSOC) - 推薦現代寫法
<?php
$mysqli = new mysqli("localhost", "root", "", "test", 3306);
$result = $mysqli->query("SELECT id, name, detail FROM userinfo");
while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
// 可讀性強、不依賴欄位順序、重構安全
echo "<tr>";
echo "<td>" . htmlspecialchars($row['id']) . "</td>";
echo "<td>" . htmlspecialchars($row['name']) . "</td>";
echo "<td>" . htmlspecialchars($row['detail']) . "</td>";
echo "</tr>";
}
// 遍歷所有欄位 (動態表頭)
if ($row = $result->fetch_array(MYSQLI_ASSOC)) {
echo "<table><tr>";
foreach (array_keys($row) as $col) { echo "<th>$col</th>"; }
echo "</tr>";
do {
echo "<tr>";
foreach ($row as $val) { echo "<td>" . htmlspecialchars($val) . "</td>"; }
echo "</tr>";
} while ($row = $result->fetch_array(MYSQLI_ASSOC));
echo "</table>";
}
?>
效能與記憶體實測
| 指標 | fetch_row | fetch_array(BOTH) | fetch_assoc |
| 記憶體/行 | 基準 1.0x | ~1.8x | ~1.3x |
| CPU 開銷 | 最低 | 最高 (建立雙重鍵) | 中等 |
| 適用場景 | 極大結果集、記憶體敏感 | 需同時用索引和名稱 | 通用推薦 |
mysqli (i = improved) 核心優勢
- 物件導向 + 過程雙介面
- 預處理語句:防注入、效能優化
- 多語句執行:
multi_query()
- 事務支援:
begin_transaction(), commit(), rollback()
- 增強除錯:
$mysqli->error_list
- SSL/壓縮連接
現代 PHP 最佳實踐 (PHP 7.4+ / 8.x)
1. 棄用 mysql_* (已移除 PHP 7)
2. 推薦 PDO (資料庫抽象層)
$pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8mb4", "root", "", [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 預設關聯陣列
PDO::ATTR_EMULATE_PREPARES => false,
]);
$stmt = $pdo->query("SELECT id, name, detail FROM userinfo");
foreach ($stmt as $row) {
echo $row['name']; // 直接用欄位名
}
3. 如果用 mysqli,請用物件導向 + FETCH_ASSOC
$mysqli = new mysqli("localhost", "root", "", "test", 3306);
$mysqli->set_charset("utf8mb4");
$result = $mysqli->query("SELECT id, name, detail FROM userinfo");
while ($row = $result->fetch_assoc()) { // 明確語義、效能最優
// ...
}
$result->free();
$mysqli->close();
總結建議
- 首選 PDO::FETCH_ASSOC:可移植、預設關聯、安全預處理
- mysqli 用 fetch_assoc():明確語義、避免雙模式記憶體浪費
- 棄用 fetch_array(MYSQLI_BOTH):除非極少數同時需索引和名稱的場景
- 永遠 htmlspecialchars() 輸出:防 XSS
- 永遠參數化查詢:防 SQL 注入
mysqli 的 "i" 代表 improved,但真正的改進在於**預處理語句**與**物件導向 API**,而非 fetch 函數的花樣。選對工具,寫對模式,才是正道。