0

我的代码当前使用mysqli::query并检查mysqli::$warning_count. 尝试将文本插入整数列时,0会被插入并生成警告。但是,我刚刚开始学习准备好的语句,对于相同的查询,不会产生警告。

这是我的代码的摘录:

$db_err_msg = 'Database Error: Failed to update profile';
$sql = "UPDATE tblProfiles SET intBookId = ? WHERE lngProfileId = ?";
$stmt = $mysqli->prepare($sql) or output_error($db_err_msg);

$book = 'CA';
$id = 10773;
$stmt->bind_param('ii', $book, $id) or output_error($db_err_msg);
$stmt->execute() or output_error($db_err_msg);
echo '$stmt->affected_rows is ', $stmt->affected_rows, "\n";

if ($mysqli->warning_count) {
    $warnings = $stmt->get_warnings();
    do {
        trigger_error('Database Warning (' . $warnings->errno . '): '
            . $warnings->message, E_USER_WARNING);
    } while ( $warnings->next() );
}
else {
    echo 'no warnings', "\n";
}

产生以下输出:

$stmt->affected_rows 为 1
无警告

请注意,该intBookId列具有TINYINT数据类型。相同的查询在使用时会生成警告mysqli::query,但在使用准备好的语句时不会。

启用严格模式无济于事。它会在使用时将警告变成错误mysqli::query,但在使用准备好的语句时,该列会以0;静默更新。

作为记录,我的应用程序在达到这一点之前已经进行了广泛的验证。但我希望通过这种额外的验证来捕捉我可能错误地错过的任何东西。

注意:切换到 PDO 超出了当前项目的范围。

为什么 MySQLi 准备好的语句会发生这种情况?这是预期的行为吗?

4

1 回答 1

1

虽然它可能不会立即明显,但这是预期的行为。

因为这行代码:

$stmt->bind_param('ii', $book, $id) or output_error($db_err_msg);

PHP 在将值发送到 MySQL 之前将其转换为整数。MySQL 接收到0该列的有效值,并且不会生成警告。

如果您不希望 PHP 执行此操作,则需要将其作为字符串发送。像这样:

$stmt->bind_param('si', $book, $id) or output_error($db_err_msg);

MySQL 将收到字符串 'CA' 并生成有关它是不正确整数值的警告。

注意:通过将所有内容作为字符串发送,MySQL 将不得不做更多的处理来将字符串转换为整数,但是当整个查询使用 mysqli::query 作为字符串发送时,它已经在这样做了。

注意:使用大于 的整数时会出现相关问题PHP_INT_MAX。如果您认为整数值将超过该最大值(取决于平台,在 32 位平台上仅为 2147483647)并且精度很重要,那么将其作为字符串发送会更安全。

于 2012-12-16T12:54:09.580 回答