PDO:: PARAM_INT важна в bindParam?

Добавить PDO::PARAM_INT или PDO::PARAM_STR имеет какое-либо значение в запросе Mysql?

$sql  = 'SELECT TagId FROM tagthread WHERE ThreadId = :ThreadId';

$stmt = $this->db->prepare($sql);
$stmt->bindParam(':ThreadId', $threadid, PDO::PARAM_INT);

$stmt->execute();

Ответ 1

Да, используйте его.

Я провел несколько тестов (с PDO:: ATTR_EMULATE_PREPARES false), и я выяснил, что кавычки вокруг значений будут разными.

Когда вы связываете целочисленное значение с PARAM_INT, в запросе не будет кавычек (строковое значение с PARAM_INT имеет кавычки). Если вы привязываете целочисленное значение с PDO::PARAM_STR, там будут кавычки, а mysql должен быть добавлен в целое число.

Примеры:

$stmt->bindParam(':ThreadId', $threadid, PDO::PARAM_INT);
$threadid = 123;
// SELECT TagId FROM tagthread WHERE ThreadId = 123
$threadid = '123test';
// SELECT TagId FROM tagthread WHERE ThreadId = '123test'
// mysql will cast 123test to 123

EDIT:

Далее я тестировал и читал эту тему. Вывод: Implicit casting is dangerous and can lead to unexpected results. Подробнее об этом здесь. Другим недостатком всегда использовать PDO::PARAM_STR является производительность. Подробнее о производительности Недостатки цитирования целых чисел в запросе Mysql?

Итак, если ваш столбец имеет тип [TINY|SMALL|MEDIUM|BIG]INT, чем использовать PARAM_INT. И в случае, если это предложение LIMIT, чем преобразование в целое число, если тип переменной в PHP не является целым числом.

Ответ 2

Изменить: зависит! См. Комментарий к своему здравому смыслу ниже.

Если значение представляет собой целое число, оно должно рассматриваться как целое число. Примените это как можно больше типов данных.

Если вы не установите для атрибута PDO:: ATTR_EMULATE_PREPARES значение false, вы получите неприятную ошибку.

Пример:

$stmt = $dbh->prepare("SELECT * FROM table123 WHERE raw_field = :field LIMIT 1 OFFSET :offset;");
$stmt->bindParam(':field',  $field);
$stmt->bindParam(':offset', $offset);

if ($map_stmt->execute())
{
    $data = stmt->fetch(PDO::FETCH_ASSOC);
}
else
{
    echo 'Error :';
    echo '<pre>';
    print_r($map_stmt->errorInfo());
    print_r($map_stmt->debugDumpParams());
    echo '</pre>';
}

Вернет обратно неприятную ошибку, содержащую:

Код ошибки: 1064 У вас есть ошибка в синтаксисе SQL; проверить руководство, соответствующее вашей версии сервера MySQL для правильного синтаксис для использования рядом с '' 0 '' в строке 1

Запрос: SELECT * FROM table123 WHERE raw_field = 'home' LIMIT 1 OFFSET '0'

Бесполезно, вы относитесь к нему как к целому числу, и оно удалит строку (например: '').

$stmt->bindParam(':offset', $offset, PDO::PARAM_INT);

В двух словах:

Вы выбираете! Строгие данные или нет.

Ответ 3

Я не могу сказать для всех драйверов, поддерживаемых PDO, но для mysql он вообще не использует PDO::PARAM_INT.

Таким образом, можно обойти bindParam и отправить вашу переменную непосредственно в execute():

$sql  = 'SELECT TagId FROM tagthread WHERE ThreadId = ?';
$stmt = $this->db->prepare($sql);
$stmt->execute([$threadid]);

Здесь ваша переменная $threadid будет бесшумно привязана как строка, но для mysql не будет единой проблемой сравнивать ее с целым значением, хранящимся в базе данных.

Единственная проблема с строковым типом bindnig - это предложение LIMIT в вашем SQL-запросе, где это приведет к ошибке, если режим эмуляции включен. Но это не должно быть проблемой, так как вы всегда можете отключить его.

Обратите внимание, что PDO::PARAM_INT не использует ваше значение. Если вы пытаетесь связать значение типа строки с помощью этого режима, он будет привязан как строка, даже если вы явно задали тип PDO::PARAM_INT. Этот режим будет использоваться только для целых значений.

Все остальные проблемы являются общими для свободной печати, и ни mysql, ни привязка PDO не имеют в них особого эффекта.

Кроме того, чтобы избежать возможных проблем , вы должны выбрать правильные типы столбцов для своих данных. Скажем, для больших целых чисел вы должны использовать BIGINT, тогда как для любых ценоподобных данных это должно быть DECIMAL. И сравнение не будет ни с чем.