在執行批量INSERT操作時,如果使用了INSERT IGNORE或ON 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::get_warnings()返回的是一個mysqli_warning對象,可以調用以下方法獲取詳細信息:
get_errno() :獲取警告的錯誤碼
get_message() :獲取警告消息文本
next() :移動到下一個警告(如果有)
通常,重複鍵衝突的警告碼是1062,對應消息中會包含“Duplicate entry”。
如果不使用INSERT IGNORE或類似的策略,重複鍵衝突會直接導致查詢失敗,返回錯誤而非警告。
get_warnings()返回的是警告鏈,需要循環遍歷獲取所有警告。
警告信息內容較為詳細,可以用來精確定位衝突的記錄。
通過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();