在执行批量 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();