使用ON DUPLICATE KEY准备好的声明

时间:2014-03-27 21:28:44

标签: php mysql

我认为这个应该很简单,但我很难做到正确。我已经搜索了一些但是对准备好的语句不熟悉我无法通过查看我在这里和其他地方找到的其他示例来弄清楚语法。无论如何这是我的代码。

if($stmt = $mysqli -> prepare("INSERT INTO user_info (city, state, website, public_contact, user, zipcode, pic, emailme) VALUES (?, ?, ?, ?, ?, ?, ?,?) 
    ON DUPLICATE KEY UPDATE (city, state, website, public_contact, user, zipcode, pic, emailme) VALUES (?, ?, ?, ?, ?, ?, ?,?)")) {
    $stmt -> bind_param("sssssssi",$city, $state, $website, $public_contact, $user, $zipcode, $pic, $emailme);
    $stmt -> execute();
    $stmt -> bind_result($result);
    $stmt -> close();
}

用户是唯一的。这个IMO只是一个语法问题,所以有人可以用正确的语法帮助我吗?非常感激。

ETA:只是为了帮助解决问题,当我删除ON DUPLICATE KEY UPDATE部分时,这确实有效,但显然,它只允许每个用户一条记录而不会更新

UPDATE:从来没有找到使用ON DUPLICATE KEY UPDATE的工作语法,所以我所做的(确实可能不是最有效的方法)是为用户检查表。如果用户存在,我运行并更新,如果不存在,我运行INSERT。以下是我的工作代码。希望这能帮助那些陷入困境的人。

 $sql = "SELECT * FROM user_info WHERE user='$user'";

 if ($result=mysqli_query($mysqli,$sql))
 {
 /* Return the number of rows in result set */
 $rows=mysqli_num_rows($result);
 /* Free result set */
 mysqli_free_result($result);
 } 

 if($rows == 0) { 
if($stmt = $mysqli -> prepare("INSERT INTO user_info (city, state, website, public_contact, user, zipcode, pic, emailme) VALUES (?, ?, ?, ?, ?, ?, ?,?) ")) {

$stmt -> bind_param("sssssssi",$city, $state, $website, $public_contact, $user, $zipcode, $pic, $emailme);
$stmt -> execute();
$stmt -> bind_result($result);
$stmt -> close();
}

} else {

if($stmt = $mysqli -> prepare("UPDATE user_info SET city=?, state=?, website=?, public_contact=?, zipcode=?, pic=?, emailme=? WHERE user='$user'")) {

$stmt -> bind_param("ssssssi",$city, $state, $website, $public_contact, $zipcode, $pic, $emailme);
$stmt -> execute();
$stmt -> bind_result($result);
$stmt -> close();
}
    }

2 个答案:

答案 0 :(得分:28)

使用INSERT的最简单方法... ON DUPLICATE KEY UPDATE是以下列方式使用VALUES子句,因此您不需要重复UPDATE子句中的参数。它们只对您在VALUES子句中传递的每列使用相同的值:

if($stmt = $mysqli -> prepare("
    INSERT INTO user_info (city, state, website, public_contact, 
        user, zipcode, pic, emailme)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?) 
    ON DUPLICATE KEY UPDATE
        city = VALUES(city),
        state = VALUES(state),
        website = VALUES(website),
        public_contact = VALUES(public_contact),
        user = VALUES(user),
        zipcode = VALUES(zipcode),
        pic = VALUES(pic),
        emailme = VALUES(emailme)") {
    $stmt -> bind_param("sssssssi",$city, $state, $website, $public_contact, 
        $user, $zipcode, $pic, $emailme);
    $stmt -> execute();
    $stmt -> close();
}

IODKU语法要求您单独设置每个列。你不能像在试图那样在一个子句中列出它们。

您应该始终报告任何对prepare()或execute()的调用中的错误。或者你可以让mysqli抛出异常:

$mysqli -> report_mode = MYSQLI_REPORT_STRICT;

此外,您不需要bind_result(),因为INSERT没有结果集:

// NO: $stmt -> bind_result($result);

答案 1 :(得分:0)

我强烈建议您查看类似Doctrine DBAL(不是ORM)的内容 - 它允许您提升密钥=>值对并使这些类型的操作在有如此多的值时更容易使用。

然后您可以执行以下操作:

try {
    $conn->insert(
    'db.`table`',
     [
       'city' => $city,
       'state' => $state
     ]);
} catch (Exception $e) {

    if( $e->getCode() !== '23000' ) {
        throw $e;
    }

    $conn->update(
    'db.`table`',
     [
       'city' => $city,
       'state' => $state
     ],
     [
       'user' => $user
     ]);
}