【问题标题】:PHP MySQL create duplicate record on unique index strange failPHP MySQL在唯一索引上创建重复记录奇怪失败
【发布时间】:2011-08-31 21:49:02
【问题描述】:

操作:创建在唯一键上重复的表记录。

好:唯一键有效,因为没有创建重复记录。

不好:我在 PHP 中使用的 mysqli 函数并没有像我预期的那样失败。

元: 我有一些 PHP(运行 5.3.6),用于处理从 AJAX POST 请求在 Mysql (5.5.9) 表中创建新记录。身份验证和输入清理和验证在我共享的代码范围之外处理。响应函数还处理以有效格式打印出响应。我要插入的表有一个自动递增的 id 列和一个唯一的 name 列。

// connect to server
$mysqli = new mysqli("localhost", "dbuser", 'dbpassword', "database");
if(mysqli_connect_errno()) {
    $response["message"] = "unable to connect to the MySQL server at 'localhost' as 'dbuser' using a password or select the database 'database' because ".mysqli_connect_errno();
    respond($response);
}

// build and run query
if ($stmt = $mysqli -> prepare("INSERT INTO `database`.`table` (`id`, `name`) VALUES (NULL, ?);")) {
    $stmt -> bind_param("s", $inputs["name"]);
    $success = $stmt -> execute();
    if ($success) {
        $response["status"] = "success";
        $response["id"] = $mysqli -> insert_id;
        respond($response);
    } else {
        $response["message"] = "failed to insert because ".$stmt -> error;
    }

    $stmt -> close();
} else {
    $response["message"] = "unable to build query because ".$mysqli -> error;
    respond($response);
}

$mysqli -> close();

这在插入新的唯一名称时按预期工作,但在尝试插入新的重复名称时不返回任何内容。我期待的

$stmt -> execute();

失败,所以我会返回一个解释错误的响应。这段代码不这样做。我发现返回由于重复而导致创建失败的唯一方法是在 close 语句之前添加 2 行代码,如下所示:

// connect to server
$mysqli = new mysqli("localhost", "dbuser", 'dbpassword', "database");
if(mysqli_connect_errno()) {
    $response["message"] = "unable to connect to the MySQL server at 'localhost' as 'dbuser' using a password or select the database 'database' because ".mysqli_connect_errno();
    respond($response);
}

// build and run query
if ($stmt = $mysqli -> prepare("INSERT INTO `database`.`table` (`id`, `name`) VALUES (NULL, ?);")) {
    $stmt -> bind_param("s", $inputs["name"]);
    $success = $stmt -> execute();
    if ($success) {
        $response["status"] = "success";
        $response["id"] = $mysqli -> insert_id;
        respond($response);
    } else {
        $response["message"] = "failed to insert because ".$stmt -> error;
    }

    $stmt -> close();
} else {
    $response["message"] = "unable to build query because ".$mysqli -> error;
    respond($response);
}

$response["message"] = "Duplicate";
respond($response);

$mysqli -> close();

我不明白的是,当查询按预期运行时,不会返回重复的响应。当查询因为试图在唯一键上插入重复而失败时,这将返回重复响应。

问题:为什么插入成功后代码块末尾没有运行响应函数?

问题:为什么由于尝试在唯一键上插入重复项而导致插入失败并没有像我预期的那样抛出异常或失败?

我也尝试将整个内容包装在一个 try catch 块中,但它没有任何帮助,因为它没有抛出任何异常。如果您能对此事有所了解,我将不胜感激。

【问题讨论】:

    标签: php mysql mysqli


    【解决方案1】:

    问题:为什么插入成功后代码块末尾没有运行response函数?

    我假设您的 respond 方法中有一个 exitdie 在它的某处停止执行。

    问题:为什么由于尝试在唯一键上插入重复项而导致插入失败不会引发异常或如我预期的那样失败?

    我认为这与您的 if 语句中的逻辑有关。

    如果你的程序进入 else 语句

    $response["message"] = "failed to insert because ".$stmt -> error;
    

    从未发送任何响应(从未调用respond 函数)。您的第二个示例有效的原因是因为代码每次都会到达该点(因为它在最后一个 else 语句之外。如果您在上面的行之后将调用移动到 respond ,您可能会发现它按预期返回消息。完整代码可能如下所示:

    // connect to server
    $mysqli = new mysqli("localhost", "dbuser", 'dbpassword', "database");
    if(mysqli_connect_errno()) {
        $response["message"] = "unable to connect to the MySQL server at 'localhost' as 'dbuser' using a password or select the database 'database' because ".mysqli_connect_errno();
        respond($response);
    }
    
    // build and run query
    if ($stmt = $mysqli -> prepare("INSERT INTO `database`.`table` (`id`, `name`) VALUES (NULL, ?);")) {
        $stmt -> bind_param("s", $inputs["name"]);
        $success = $stmt -> execute();
        if ($success) {
            $response["status"] = "success";
            $response["id"] = $mysqli -> insert_id;
            respond($response);
        } else {
            $response["message"] = "failed to insert because ".$stmt -> error;
            respond($response); // <-- this is the bit you need
        }
    
        $stmt -> close();
    } else {
        $response["message"] = "unable to build query because ".$mysqli -> error;
        respond($response);
    }
    
    $mysqli -> close();
    

    【讨论】:

    • 在这里我想我快疯了。果然我错过了对响应函数的调用。谢谢你的帮助。有时最好走开,稍后再看一遍。感谢您帮助我。
    • 没问题,发生在我们最好的人身上:)
    【解决方案2】:

    尝试从$stmt-&gt;errorCode()$stmt-&gt;errorInfo()获取错误信息

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-03
      • 1970-01-01
      • 2016-01-26
      • 2015-03-22
      相关资源
      最近更新 更多