Как работает параметризованный запрос PDO - PullRequest
8 голосов
/ 16 сентября 2010

ПОЖАЛУЙСТА, ВНИМАТЕЛЬНО ПРОЧИТАЙТЕ ВОПРОС. Это не обычно глупо "мой код не работает !!!" вопрос.

Когда я запускаю этот код с предполагаемой ошибкой

try {
  $sth = $dbh->prepare("SELECT id FROM users WHERE name INN(?,?) ");
  $sth->execute(array("I'm","d'Artagnan"));
} catch (PDOException $e) {
    echo $e->getMessage();
}

Я получаю это сообщение об ошибке

У вас есть ошибка в синтаксисе SQL ... рядом с INN ('I \' m ',' d \ 'Artagnan') 'в строке 1

Но я годами думал, что запрос и данные отправляются на сервер отдельно и никогда не мешают. Таким образом, у меня есть несколько вопросов (хотя я сомневаюсь, что кто-то получил ответ ...)

  1. Откуда он получает такое знакомое строковое представление - в кавычках и экранированный? Это сделано специально для сообщения об ошибке или это часть фактического запроса?
  2. Как это работает в реальности? Заменяет ли он заполнитель данными или нет?
  3. Есть ли способ получить весь запрос, а не только его часть, для целей отладки?

Обновление

mysqli делает это как положено: выдает ошибку говорит near 'INN(?,?)'

Ответы [ 2 ]

7 голосов
/ 16 сентября 2010

попробуйте добавить

$dbh->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );

;)

7 голосов
/ 16 сентября 2010

Я не уверен во всех деталях, но постараюсь ответить.

  1. Цитирование происходит на стороне базы данных. База данных экранирует и дезинфицирует все значения (см. Пункт 2), которые она получает, чтобы ее правильно интерпретировали. В момент возникновения ошибки база данных (в данном случае MySQL) выводит запрос, который она пыталась выполнить. Это не было бы так полезно, если бы просто показало подготовленную часть.

  2. Нет, это не так. Во время подготовки запрос компилируется на стороне сервера. Когда запрос выполняется со значениями, передаются только значения. Это почти то же самое, что вызов PREPARE и EXECUTE для базы данных напрямую.

  3. Это зависит от базы данных, которую вы используете. Например, MySQL может записывать все запросы в файл журнала (для этого проверьте настройки my.cnf). Но вы также можете использовать debugDumpParams () на стороне PHP.

Надеюсь, это немного помогло.

...