После публикации этого вопроса MySQL update или insert или die query, я изменил использование PDO, но у меня возникли проблемы с использованием дублирующей фразы обновления ключа.
Вот пример данных моего массива
array(114) { ["fname"]=> string(6) "Bryana" ["lname"]=> string(6) "Greene" ["m080"]=> string(1) "c" ["t080"]=> string(1) "-" ["w080"]=> string(1) "-" ["r080"]=> ["notes"]=> string(4) "yoyo"}
На самом деле есть 113 полей, но я не хотел терять пространство, показывая им все здесь. В настоящее время я пытаюсь ввести INSERT / UPDATE в мою базу данных с помощью следующего кода
try { $dbh = new PDO('login info here'); $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); $stmt = $dbh->prepare( 'INSERT INTO fhours ('.implode(",", array_keys($faculty)).')'. ' VALUES (:'.implode(",:", array_keys($faculty)).')'. ' ON DUPLICATE KEY UPDATE :fieldlist'); $stmt->bindParam(':field_list', $field_list); foreach($faculty as $key=>$val){ $stmt->bindParam(':'.$key, $val); $fields[] = sprintf("%s = :%s", $key, $key); } $field_list = join(',', $fields); //echo $stmt->debugDumpParams(); $stmt->execute(); } catch(PDOException $e){ echo $e->getMessage(); exit(); }
Я получаю номер параметра Invalid: параметр не был указан в сообщении об ошибке. Я уверен, что мои проблемы заключаются в ON DUPLICATE KEY UPDATE :fieldlist');
но я сделал так много разных попыток, и никто из них не работал. Должен ли я вообще использовать ON DUPLICATE KEY UPDATE
?
Кроме того, я новичок в синтаксисе: и ::, означает :name
означает, что это именованная переменная типа $name
и делает PDOStatement::bindValue
вроде как PDOStatement->bindValue
?
В ответ на первые два комментария ниже я обновил код таким образом (но все же безрезультатно, debugDumpParams говорит, что у меня нет параметров). Кроме того, зачем создавать параметры $array_of_parameters
когда он становится тем же самым массивом, что и $faculty
?
//grab form data $faculty = $_POST; $fname = $_POST['fname']; $lname = $_POST['lname']; //delete the submit button from array unset($faculty['submit']); $array_of_parameters = array(); foreach($faculty as $key=>$val){ $array_of_parameters[$key] = $val; $fields[] = sprintf("%s=?", $key); } $field_list = join(',', $fields); try { $dbh = new PDO('mysql:host=localhost;dbname=kiosk', 'kiosk', 'K10$k'); $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); $update = 'UPDATE fhours SET '.$field_list. 'WHERE fname="'.$fname.'" AND '. 'lname="'.$lname.'"'; $stmt = $dbh->prepare($update); //echo $stmt->debugDumpParams(); $stmt->execute(array($array_of_parameters)); if($stmt->rowCount() == 0){ $insert = 'INSERT INTO fhours ('.implode(",", array_keys($faculty)).')'. ' VALUES (:'.implode(",:", array_keys($faculty)).')'; $stmt = $dbh->prepare($insert); $stmt->execute(array($array_of_parameters)); } } catch(PDOException $e){ echo $e->getMessage(); exit(); } $dbh=null;
с//grab form data $faculty = $_POST; $fname = $_POST['fname']; $lname = $_POST['lname']; //delete the submit button from array unset($faculty['submit']); $array_of_parameters = array(); foreach($faculty as $key=>$val){ $array_of_parameters[$key] = $val; $fields[] = sprintf("%s=?", $key); } $field_list = join(',', $fields); try { $dbh = new PDO('mysql:host=localhost;dbname=kiosk', 'kiosk', 'K10$k'); $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); $update = 'UPDATE fhours SET '.$field_list. 'WHERE fname="'.$fname.'" AND '. 'lname="'.$lname.'"'; $stmt = $dbh->prepare($update); //echo $stmt->debugDumpParams(); $stmt->execute(array($array_of_parameters)); if($stmt->rowCount() == 0){ $insert = 'INSERT INTO fhours ('.implode(",", array_keys($faculty)).')'. ' VALUES (:'.implode(",:", array_keys($faculty)).')'; $stmt = $dbh->prepare($insert); $stmt->execute(array($array_of_parameters)); } } catch(PDOException $e){ echo $e->getMessage(); exit(); } $dbh=null;
То, что вы пытались сделать, – это динамически построить строку SQL, которая будет параметризоваться. Параметрами :paramname
как ожидается, являются одиночные значения, сопоставленные значениям столбцов, параметрам предложения и т. Д. Вместо этого вы использовали $fields[] = sprintf("%s = :%s", $key, $key);
для создания строки полей :paramname
, чтобы подключиться к запросу. Это просто не будет работать в параметризованной инструкции.
Вместо того, чтобы делать ON DUPLICATE KEY UPDATE :fieldlist
, вы должны собрать всю строку sql перед передачей ее в prepare()
.
Затем вместо использования bindParam()
для привязки каждого отдельно, вы можете использовать альтернативный синтаксис для execute()
для передачи в массив ожидаемых параметрических значений. Они должны быть в правильном порядке или иметь ключи массива с теми же именами, что и параметры :param
в вашем SQL. Дополнительную информацию и примеры см. В документах.
$array_of_parameters = array(); foreach($faculty as $key=>$val){ $array_of_parameters[$key] = $val); } $stmt->execute($array_of_parameters);
РЕДАКТИРОВАТЬ Для правильного использования параметров в UPDATE
выполните следующие действия:
// Create your $field_list before attempting to create the SQL statement $field_list = join(',', $fields); $update = 'UPDATE fhours SET '.$field_list. 'WHERE fname=:fname AND lname=:lname'; // Here, echo out $update to make sure it looks correct // Then add the fname and lname parameters onto your array of params $array_of_parameters[] = $_POST['fname']; $array_of_parameters[] = $_POST['lname']; // Now that your parameters array includes all the faculty in the correct order and the fname & lname, // you can execute it. $stmt->prepare($update); $stmt->execute($array_of_parameters);
Имя с двоеточием – это не что иное, как именованный заполнитель. Когда вы переходите на привязку своих параметров, вы просто привязываете свой placeholder к некоторой произвольной ценности.
ON DUPLICATE KEY UPDATE
не очень дружелюбен к нескольким СУБД, но если вы подключены к совместимой базе данных, он должен работать (поскольку я не верю, что PDO заблокирует все это, но я могу ошибаться). Я бы не использовал его только ради мобильности. Вы можете проверить, как вы привязываете свои полевые списки, хотя bindparam должен выполнять только один параметр, а это коды, которые не должны указываться как значения (которые будут связаны с параметром bind).
Я проектирую upserts, выполняя максимум два запроса: Update, затем Insert. Сначала я обновлю и проверю, больше ли число обновленных строк. Если затронутые строки равны 0, запустите Insert.
Просто пустой комментарий, 113 полей – это много полей, вы можете пострадать от некоторой производительности таблицы, если не будете осторожны