【问题标题】:Can I safely assume this INSERT succeeded?我可以安全地假设这个 INSERT 成功了吗?
【发布时间】:2012-12-01 16:57:34
【问题描述】:

我正在使用开启严格模式的 MySQL。我正在通过 HTML 表单插入用户提供的数据。我已经完成了所有验证,这是最后一步。

这是我的 PHP 代码的摘录:

$sql = 'SET sql_mode = TRADITIONAL'; //last chance data validation
$mysqli->query($sql) or output_error('Database Error: Failed to set SQL mode');

$db_err_msg = 'Database Error: Failed to update profile summary';
$sql = "INSERT INTO {$tables['text']} (lngProfileId, memProfileText) VALUES(?, ?)
    ON DUPLICATE KEY UPDATE memProfileText = VALUES(memProfileText)";
$stmt = $mysqli->prepare($sql) or output_error($db_err_msg);
$stmt->bind_param('is', $profile_id, $_POST['memProfileText'])
    or output_error($db_err_msg);
$stmt->execute() or output_error($db_err_msg);
$stmt->close();

//if code reaches this point, can it assume insert/update succeeded?

注意: output_error 是我的致命错误处理程序。它不会返回;它退出了。

我需要检查警告吗?或者我可以安全地假设插入/更新成功吗?是否存在即使打开严格模式也可能导致警告而不是错误的情况?

编辑:我只关心应该被视为致命错误的事情。如果它是更新而不是插入,那对我来说无关紧要。这不是错误。

此外,last_insert_idaffected_rows 在这种情况下毫无意义。如果用户没有进行任何更改,affected_rows 将为 0,并且 last_insert_id 的值不会被更新。

在这种情况下我对成功的定义:

  • 它插入了记录或更新了记录,或者如果没有进行任何更改,则什么也不做
  • 它没有“默默地破坏我的数据”

许多新手程序员犯了一个错误假设查询成功而没有检查返回值或警告。他们的代码工作...在正常情况下。

我的问题是: “考虑到我的代码,开启了严格模式,并且我已经完成了错误检查,假设查询成功是否安全?这是正确的吗?还是错误的假设?我是否也应该检查警告还是多余的?”

【问题讨论】:

  • 你测试了吗?如果它有效,它就有效。
  • 是的,我测试过了。它适用于我扔给它的所有东西。但我想确保没有我不考虑的情况。我正在努力确保编写健壮的代码。
  • 不解决不存在的问题。您不想重新测试 mysql、php 驱动程序的功能。或者你也可以自己写驱动,DB

标签: php mysql error-handling


【解决方案1】:

你应该检查mysqli::info()函数的值。

如果它插入数据,字符串将如下所示,

Records: 1 Duplicates: 0 Warnings: 0

另一个函数是mysqli::affected_rows。它返回上次插入/更新/删除查询受影响的行数。

【讨论】:

  • mysqli::$info() 仅适用于某些语句。对于单个插入,它返回一个空字符串。 mysqli::$affected_rows 将返回 0 如果该行已经存在并且未更改。我的问题是问是否我需要检查警告而不是如何获取该信息。
【解决方案2】:

是的,您可以放心地假设,但只是为了仔细检查获取插入的最新记录的 ID。如果有id,则插入然后

【讨论】:

  • 在这种情况下,最后一个插入的 id 不会告诉我太多。请参阅我的问题的编辑。
【解决方案3】:

虽然我认为这可能是一个安全的假设,但我认为比抱歉更安全。我在close语句之前的execute语句之后直接添加了以下代码。

//I think this is probably redundant, but just in case
if ($mysqli->warning_count) {
    $warnings = $stmt->get_warnings();
    do {
        trigger_error('Database Warning (' . $warnings->errno . '): '
            . $warnings->message, E_USER_WARNING);
    } while ( $warnings->next() );
}

我添加了评论,以便我记得我为什么这样做。

【讨论】:

    猜你喜欢
    • 2011-09-20
    • 1970-01-01
    • 2021-09-09
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-15
    • 1970-01-01
    相关资源
    最近更新 更多