Я думаю, что это должно быть довольно легко, но у меня проблемы с этим. Я немного искал, но был новичком в подготовленных утверждениях. Я не могу понять синтаксис, глядя на другие примеры, которые я нашел здесь и в других местах. Так или иначе, вот мой код.
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(); }
пользователь является уникальным. Эта ИМО – это просто синтаксическая проблема, поэтому кто-нибудь может помочь мне с правильным синтаксисом? Очень признателен.
ETA: просто для того, чтобы помочь устранить проблему, это работает по назначению, когда я удаляю часть ON DUPLICATE KEY UPDATE, но, очевидно, она разрешает только одну запись для каждого пользователя и не будет обновлять
UPDATE: никогда не смог найти рабочий синтаксис для использования UPDATE ON DUPLICATE KEY UPDATE, поэтому то, что я сделал вместо этого (возможно, не самый эффективный способ), проверил таблицу перед рукой для пользователя. Если пользователь существует, я запускаю и 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(); } }
Самый простой способ использовать 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 требует, чтобы вы устанавливали каждый столбец отдельно. Вы не можете перечислить их все в одном пункте, как вы пытались сделать.
Вы всегда должны сообщать о любых ошибках из любого вызова, чтобы подготовить () или выполнить (). Или вы можете сделать исключения mysqli throw:
$mysqli -> report_mode = MYSQLI_REPORT_STRICT;
Кроме того, вам не нужно bind_result (), так как нет набора результатов из INSERT:
// NO: $stmt -> bind_result($result);
Я настоятельно рекомендую взглянуть на что-то вроде 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 ]); }