PHP — MySQLi — Вставка с ВЫБОРОМ в конце не работает

#php #sql #mysqli

#php #sql #mysqli

Вопрос:

У меня есть эта функция в PHP. Я пытаюсь вставить (если это необходимо), а затем получить app_id из таблицы.

 private function addApp($bundle_identifier,$os_id) {

$driver = new mysqli_driver();
$driver->report_mode = MYSQLI_REPORT_ALL;

//Insert or update app details
if ($stmt = $this->db->prepare("INSERT IGNORE INTO app (app_identifier,os_id) VALUES (?,?); SELECT app_id FROM app WHERE app_identifier = ? AND os_id = ?")){
    $stmt->bind_param("ssss", $bundle_identifier,$os_id,$bundle_identifier,$os_id);
    $stmt->execute();
    $stmt->bind_result($app_id);

    if (!isset($app_id)) {
      echo "is set";
       $app_id=$stmt->insert_id;
    }
}

if($this->db->commit()){
  return $app_id;
}

return  0;
}
  

Проблема здесь в том, что stmt всегда имеет значение false с ошибкой:

Неперехваченное исключение ‘mysqli_sql_exception’ с сообщением ‘У вас ошибка в вашем синтаксисе SQL; проверьте руководство, соответствующее вашей версии сервера MySQL, чтобы найти правильный синтаксис для использования рядом ‘ВЫБЕРИТЕ app_id ИЗ приложения, ГДЕ app_identifier = ? И os_id = ?’ в строке 1′

Странно то, что этот запрос отлично работает в моем SQL. Это ограничение mysqli?

Комментарии:

1. Я думаю, execute выполняется один оператор, а не несколько операторов.

2. Примечание: if (!isset($app_id)) { echo "is set"; противоречиво.

3. @Fred-ii- это для целей тестирования

4. Какой результат вы привязываете? Вы INSERTING и не SELECTING .

5. Я выбираю в конце запроса. В этом проблема

Ответ №1:

Согласно http://php.net/manual/en/mysqli.prepare.php :

Запрос должен состоять из одного оператора SQL.

Что в основном отвечает на ваш вопрос. Вы должны использовать два вызова db для двух запросов. Или используйте что-то вродеhttp://php.net/manual/en/mysqli.multi-query.php

Приведенное ниже приведено только для информации, поскольку оно относится к PDO, в то время как вопрос касается mysqli. Хотя в целом это полезно.

Я думаю, что причина, по которой это работает в mysql, но не в mysqli, заключается в том, что последний поддерживает подготовленные операторы изначально, в то время как первый использует эмуляцию. Поскольку ваше выражение содержит два запроса, все связанные параметры задаются драйвером для первого запроса (из которых использует два и отбрасывает два других). Затем второй запрос не получает параметров, и поэтому вопросительные знаки являются синтаксическими ошибками. С помощью эмуляции подготовленных операторов PHP фактически заменяет вопросительные знаки правильно экранированными значениями и, таким образом, формирует два допустимых запроса.

Вы можете включить эмуляцию с помощью $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true) , однако это может немного повлиять на производительность.

Смотрите также http://www.php.net/manual/en/pdo.setattribute.php

Комментарии:

1. Спасибо за ваш ответ. Я попробовал это и теперь получаю эту ошибку: Call to undefined method mysqli::setAttribute()

2. правильно… По какой-то причине я думал, что вы используете PDO — отсюда ссылка на функцию PDO и константу. Я не думаю, что низкоуровневый драйвер mysqli поддерживает подобную эмуляцию. Таким образом, вы можете либо поместить значения в запрос напрямую (как я вижу, это числа, поэтому вы можете сделать запрос безопасным, применив intval к переменным перед отправкой их в запрос), либо разделить это на два вызова db.

3. Я даже пытался жестко запрограммировать результаты, но ничего не происходит. Как только я удалил «ВЫБРАТЬ», все работает нормально.

4. @BlackM Я обновил ответ. В документации четко указано, что «подготовить» работает только с одним запросом.