Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

PHP PDO в чем разница ATTR_EMULATE_PREPARES, false и true

#php #mysql #pdo


Пробовал вставлять значения разных типов данных в колонки с разными типами данных
при ATTR_EMULATE_PREPARES, false и true, разницы не увидел, может кто объяснить в чем
отличие?

//типы колонов r1 = int, r2 = varchar, r3 = bool

$pdo = new PDO('mysql:host=localhost;dbname=test;charser=utf8', 'root', '');
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$smt = $pdo->prepare('INSERT INTO pwnd (r1, r2 ,r3) VALUES (:r1, :r2, :r3)');
echo $smt->execute([':r1' => 'a2', ':r3' => 'false', ':r2' => true]);

    


Ответы

Ответ 1



С PDO::ATTR_EMULATE_PREPARES в значении true за обработку подготовленных выражений отвечает сам PDO. В базу данных передаётся чистый запрос с уже подставленными и корректно экранированными данными (только в dsn не забывайте правильно charset указывать). PDO::ATTR_EMULATE_PREPARES в значении false именно использует штатный механизм СУБД для подготовки запроса и затем отдельным обращением передаёт данные для этого запроса. Т.е. нормальные, реальные подготовленные выражения. Из не очевидных моментов: для сложных запросов дико удобно использовать именованные параметры несколько раз. Какой-нибудь where user_from = :id or user_to = :id и передать только один id. Такое возможно только с эмуляцией запросов. специфика конкретных СУБД. Какие-то СУБД из тех, что умеет PDO могут не уметь подготовленные выражения. Например, очень популярный PgBouncer (пул коннектов для PostgreSQL) не умеет обрабатывать подготовленные выражения. С эмуляцией выражений можно в коде проекта пользоваться удобствами API с prepare вопрос с тем, что подготовленный запрос разбирается и строит план один раз и затем только выполняется - на самом деле гораздо сложнее. Тот же mysql сохраняет запрос только в рамках соединения. Поэтому в типичном сценарии использования "подготовил, выполнил, закрыл соединение" никаких плюсов реальное препарирование не даёт. А кэширование плана между соединениями - по-моему (сам с этой СУБД не работал), есть в Oracle и приносит некоторое количество головной боли, ведь оптимальный план запроса в немалой степени зависит от самих данных.

Ответ 2



Отличие в том, что к типам подставляемых переменных режим эмуляции не имеет ни малейшего отношения. За тип привязываемой переменной отвечает третий параметр в bindParam/bindValue. В то время как для всех передаваемых в execute() переменных по умолчанию используется тип "строка". Поэтому ставить ставить вопрос про связь типов и режима эмуляции попросту некорректно - эти понятия никак между собой не связаны.

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

Отправить комментарий