當前位置: 首頁> 最新文章列表> 使用mysqli::get_warnings 檢測批量INSERT 時的重複鍵問題

使用mysqli::get_warnings 檢測批量INSERT 時的重複鍵問題

gitbox 2025-05-29

為什麼需要用mysqli::get_warnings()

在執行批量INSERT操作時,如果使用了INSERT IGNOREON DUPLICATE KEY UPDATE ,MySQL 並不會直接報錯,而是生成警告(warnings)。這時候,我們很難通過錯誤捕捉機制得知具體的衝突信息。 mysqli::get_warnings()可以拿到這些警告,幫助我們理解哪些記錄發生了衝突。

示例代碼

假設有如下數據表users ,定義了一個唯一鍵email

 CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50),
  email VARCHAR(100) UNIQUE
);

我們嘗試批量插入多條數據,其中包含重複的email

 <?php
$mysqli = new mysqli("localhost", "root", "password", "testdb");

if ($mysqli->connect_errno) {
    die("連接數據庫失敗: " . $mysqli->connect_error);
}

// 預備批量插入的SQL語句
$sql = "INSERT IGNORE INTO users (name, email) VALUES 
        ('Alice', '[email protected]'), 
        ('Bob', '[email protected]'),
        ('Charlie', '[email protected]')";  // 注意這裡的email重複

if ($mysqli->query($sql)) {
    echo "插入完成。<br>";

    // 通過 get_warnings() 检测是否有重複键冲突警告
    if ($warning = $mysqli->get_warnings()) {
        do {
            echo "警告級別: " . $warning->get_errno() . "<br>";
            echo "警告消息: " . $warning->get_message() . "<br>";
        } while ($warning->next());
    } else {
        echo "無警告信息。";
    }
} else {
    echo "插入失敗: " . $mysqli->error;
}

$mysqli->close();

在上面代碼中,我們用INSERT IGNORE來嘗試插入數據。當遇到重複的email時,MySQL 會忽略該條記錄的插入,但會生成警告。通過$mysqli->get_warnings()可以獲取這些警告信息,從而知道存在重複鍵衝突。

mysqli_warning對象詳解

mysqli::get_warnings()返回的是一個mysqli_warning對象,可以調用以下方法獲取詳細信息:

  • get_errno() :獲取警告的錯誤碼

  • get_message() :獲取警告消息文本

  • next() :移動到下一個警告(如果有)

通常,重複鍵衝突的警告碼是1062,對應消息中會包含“Duplicate entry”。

注意事項

  1. 如果不使用INSERT IGNORE或類似的策略,重複鍵衝突會直接導致查詢失敗,返回錯誤而非警告。

  2. get_warnings()返回的是警告鏈,需要循環遍歷獲取所有警告。

  3. 警告信息內容較為詳細,可以用來精確定位衝突的記錄。


通過mysqli::get_warnings() ,我們可以在批量插入時更加優雅地處理重複鍵衝突,不僅保證數據插入的連續性,還能及時獲知數據質量問題,提高程序的健壯性。


 <?php
$mysqli = new mysqli("localhost", "root", "password", "testdb");

if ($mysqli->connect_errno) {
    die("連接數據庫失敗: " . $mysqli->connect_error);
}

$sql = "INSERT IGNORE INTO users (name, email) VALUES 
        ('Alice', '[email protected]'), 
        ('Bob', '[email protected]'),
        ('Charlie', '[email protected]')";

if ($mysqli->query($sql)) {
    echo "插入完成。<br>";

    if ($warning = $mysqli->get_warnings()) {
        do {
            echo "警告級別: " . $warning->get_errno() . "<br>";
            echo "警告消息: " . $warning->get_message() . "<br>";
        } while ($warning->next());
    } else {
        echo "無警告信息。";
    }
} else {
    echo "插入失敗: " . $mysqli->error;
}

$mysqli->close();