Я хотел бы включить подготовленные инструкции PDO INSERT и UPDATE в INSERT и ON DUPLICATE KEY UPDATE, так как я думаю, что это будет намного более эффективно, чем то, что я сейчас делаю, но мне трудно понять правильный синтаксис для использовать с именованными заполнителями и bindParam.
Я нашел несколько похожих вопросов на SO, но я новичок в PDO и не смог успешно адаптировать код для своих критериев. Это то, что я пробовал, но он не работает (он не вставляет и не обновляет):
try { $stmt = $conn->prepare('INSERT INTO customer_info (user_id, fname, lname) VALUES(:user_id, :fname, :lname)' 'ON DUPLICATE KEY UPDATE customer_info SET fname= :fname, lname= :lname WHERE user_id = :user_id'); $stmt->bindParam(':user_id', $user_id); $stmt->bindParam(':fname', $_POST['fname'], PDO::PARAM_STR); $stmt->bindParam(':lname', $_POST['lname'], PDO::PARAM_STR); $stmt->execute(); }
Это упрощенная версия моего кода (у меня есть несколько запросов, и каждый запрос имеет от 20 до 50 полей). В настоящее время я обновляю сначала и проверяю, больше ли число обновленных строк, чем 0, а если нет, то запускается вставка, и каждый из этих запросов имеет собственный набор операторов bindParam.
ON DUPLICATE KEY
синтаксис ON DUPLICATE KEY
.
$stmt = $conn->prepare('INSERT INTO customer_info (user_id, fname, lname) VALUES(:user_id, :fname, :lname) ON DUPLICATE KEY UPDATE fname= :fname2, lname= :lname2'); $stmt->bindParam(':user_id', $user_id); $stmt->bindParam(':fname', $_POST['fname'], PDO::PARAM_STR); $stmt->bindParam(':lname', $_POST['lname'], PDO::PARAM_STR); $stmt->bindParam(':fname2', $_POST['fname'], PDO::PARAM_STR); $stmt->bindParam(':lname2', $_POST['lname'], PDO::PARAM_STR);
Вам не нужно помещать имя таблицы или SET
в предложение ON DUPLICATE KEY
, и вам не нужно предложение WHERE
(оно всегда обновляет запись с помощью дубликата ключа).
См. http://dev.mysql.com/doc/refman/5.5/en/insert-on-duplicate.html.
У вас также была синтаксическая ошибка PHP: вы разбиваете запрос на две строки.
ОБНОВИТЬ:
Чтобы связать несколько параметров:
function bindMultiple($stmt, $params, &$variable, $type) { foreach ($params as $param) { $stmt->bindParam($param, $variable, $type); } }
Затем назовите его:
bindMultiple($stmt, array(':fname', ':fname2'), $_POST['fname'], PDO::PARAM_STR);
ИМХО ниже – это правильный ответ для тех, кто снова сталкивается с этим.
Примечание: этот оператор предполагает, что user_id является КЛЮЧЕМ в таблице.
ЗАЯВЛЕНИЕ действительно было неправильным, но принятый ответ был не совсем правильным.
Если вы вставляете и обновляете с использованием тех же значений (и не обновляете их разными значениями), это исправление псевдокода запроса:
try { //optional if your DB driver supports transactions $conn->beginTransaction(); $stmt = $conn->prepare('INSERT INTO customer_info (user_id, fname, lname) ' . 'VALUES(:user_id, :fname, :lname)' . 'ON DUPLICATE KEY UPDATE fname=VALUES(fname), lname=VALUES(lname)'); $stmt->bindParam(':user_id', $user_id); $stmt->bindParam(':fname', $_POST['fname'], PDO::PARAM_STR); $stmt->bindParam(':lname', $_POST['lname'], PDO::PARAM_STR); $stmt->execute(); //again optional if on MyIASM or DB that doesn't support transactions $conn->commit(); } catch (PDOException $e) { //optional as above: $conn->rollback(); //handle your exception here $e->getMessage() or something }