萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

PHP mysql_query 返回值詳解與遷移指南 (mysqli/PDO)

mysql_query 返回值語義

SQL 類型 成功返回 失敗返回 說明
SELECT / SHOW / DESCRIBE / EXPLAIN Resource (結果集句柄) FALSE 需配合 mysql_fetch_assoc() 等獲取數據
INSERT / UPDATE / DELETE / REPLACE TRUE FALSE 影響行數用 mysql_affected_rows() 獲取
CREATE / DROP / ALTER / TRUNCATE TRUE FALSE DDL 操作

經典錯誤用法

 0) {
    $row = mysql_fetch_assoc($result);
    echo "找到用戶: {$row['name']}";
} else {
    echo "用戶不存在";
}

// ❌ 錯誤:INSERT 判斷影響行數
$sql = "INSERT INTO users (name) VALUES ('test')";
if (mysql_query($sql)) {  // 只能知道語法/執行是否成功
    echo "插入成功";      // 即使主鍵衝突 IGNORE 也返回 TRUE
}

// ✅ 正確:檢查影響行數
mysql_query($sql);
if (mysql_affected_rows() > 0) {
    echo "插入成功,ID: " . mysql_insert_id();
} else {
    echo "插入失敗或無變化: " . mysql_error();
}
?>

完整參數說明

resource mysql_query ( string $query [, resource $link_identifier = NULL ] )

參數:
  query          - SQL 語句 (不以分號結尾)
  link_identifier - 可選,mysql_connect() 返回的連接資源,省略則用最後打開的連接

返回:
  SELECT 類: resource | FALSE
  其他:    TRUE | FALSE

常見函數配套使用

";
}

// 3. 釋放結果集 (長腳本必做)
mysql_free_result($result);

// 4. 獲取插入 ID
mysql_query("INSERT INTO logs (msg) VALUES ('test')", $link);
$new_id = mysql_insert_id($link);

// 5. 獲取影響行數
$affected = mysql_affected_rows($link);

// 6. 關閉連接
mysql_close($link);
?>

⚠️ 重大警告:mysql_* 函數已棄用並移除

時間線

  • PHP 5.5.0 (2013) - 標記棄用,產生 E_DEPRECATED
  • PHP 7.0.0 (2015) - 完全移除,代碼將報 Fatal Error

現有項目 必須遷移 到 mysqli 或 PDO。

遷移方案 A:mysqli (面向過程風格,最接近 mysql_*)

";
}
mysqli_free_result($result);

// 寫入
mysqli_query($mysqli, "INSERT INTO logs (msg) VALUES ('test')");
$new_id = mysqli_insert_id($mysqli);
$affected = mysqli_affected_rows($mysqli);

// 關閉
mysqli_close($mysqli);
?>

遷移方案 B:mysqli (面向對象風格,推薦)

connect_errno) {
    die('連接失敗: ' . $mysqli->connect_error);
}
$mysqli->set_charset('utf8mb4');

// 預處理語句 (防注入、性能更好)
$stmt = $mysqli->prepare("SELECT id, name, email FROM users WHERE status = ? AND created_at > ?");
$stmt->bind_param('is', $status, $date);
$status = 1;
$date = '2024-01-01';
$stmt->execute();
$result = $stmt->get_result();

while ($row = $result->fetch_assoc()) {
    echo "{$row['id']}: {$row['name']} <{$row['email']}>
"; } $result->free(); $stmt->close(); // 事務 $mysqli->begin_transaction(); try { $mysqli->query("UPDATE accounts SET balance = balance - 100 WHERE id = 1"); $mysqli->query("UPDATE accounts SET balance = balance + 100 WHERE id = 2"); $mysqli->commit(); } catch (Exception $e) { $mysqli->rollback(); throw $e; } $mysqli->close(); ?>

遷移方案 C:PDO (跨數據庫、最通用)

 PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false,  // 使用真實預處理
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
$pdo = new PDO($dsn, 'user', 'pass', $options);

// 查詢
$stmt = $pdo->prepare("SELECT id, name FROM users WHERE status = ?");
$stmt->execute([1]);
foreach ($stmt as $row) {
    echo "{$row['id']}: {$row['name']}
"; } // 寫入 + 事務 $pdo->beginTransaction(); try { $stmt = $pdo->prepare("INSERT INTO logs (msg, level) VALUES (?, ?)"); $stmt->execute(['User login', 'INFO']); $log_id = $pdo->lastInsertId(); $pdo->commit(); } catch (Exception $e) { $pdo->rollBack(); throw $e; } ?>

對比總結:mysql vs mysqli vs PDO

特性 mysql (已移除) mysqli (過程/對象) PDO
PHP 版本支持 ≤ 5.6 5.0+ 5.1+
預處理語句 ❌ ✅ ✅
事務控制 手動 SQL API + SQL API (統一接口)
多數據庫支持 ❌ ❌ 只支持 MySQL ✅ 12+ 驅動
異步查詢 ❌ ✅ (mysqli_poll) ❌
學習曲線 低 低 (過程式) 中
推薦場景 不推薦 純 MySQL 專案、遷移舊代碼 新項目、多數據庫、框架開發

自動化遷移工具

# 1. Rector (自動重構 PHP 代碼)
composer require rector/rector --dev
vendor/bin/rector process src --config rector.php

# rector.php
use Rector\Set\ValueObject\SetList;
use Rector\Config\RectorConfig;
return static function (RectorConfig $config) {
    $config->sets([SetList::MYSQL_TO_MYSQLI]);
};

# 2. 手動查找替換 (IDE 正則)
# mysql_query\(       → mysqli_query($link,
# mysql_fetch_assoc\(  → mysqli_fetch_assoc(
# mysql_error\(\)      → mysqli_error($link)
# mysql_connect\(      → mysqli_connect(

行動建議:立即停止使用 mysql_* 函數。新項目直接用 PDO;存量項目用 Rector 自動遷移至 mysqli 面向對象風格,配合預處理語句徹底根治 SQL 注入風險。

copyright © 萬盛學電腦網 all rights reserved