PHP MySQL在唯一索引上创建重复记录奇怪失败

时间:2011-08-31 21:49:03

标签: php mysql mysqli

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

好:唯一键正在运行,因为未创建重复记录。

错误:我在PHP中使用的mysqli函数没有以我期望的方式失败。

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

// 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块中包装整个东西,但它没有任何帮助,因为它没有抛出任何异常。如果你能对这件事情有所了解,我将不胜感激。

2 个答案:

答案 0 :(得分:3)

问题:为什么成功的插入不会在代码块的末尾运行响应函数?

我认为您的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();

答案 1 :(得分:1)

尝试从$stmt->errorCode()$stmt->errorInfo()

获取错误信息