Как уже упоминалось в моем комментарии к вашему ответу.
Документация PHP по PDOStatement::execute
состояния.
Массив значений с таким количеством элементов, сколько связанных параметров в выполняемой инструкции SQL.Все значения рассматриваются как PDO::PARAM_STR
.Источник: https://www.php.net/manual/en/pdostatement.execute.php
Дополнительно PDOStatement::fetch()
возвращает false
, если больше нет результатов или произошел сбой.
Возвращаемое значение этой функции в случае успеха зависит от типа выборки.Во всех случаях FALSE
возвращается при ошибке.
Пример https://3v4l.org/NVECJ
$pdo = new \PDO('sqlite::memory:', null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
$pdo->query('CREATE TABLE foo(id INTEGER)');
$stmt = $pdo->prepare('SELECT * FROM foo');
$stmt->execute();
var_dump($stmt->fetch());
//bool(false)
Если вам необходимо явно определить тип данных, отличный от PDO::PARAM_STR
дляпараметр, отправляемый в MySQL, вы будете использовать PDOStatement::bindParam
или PDOStatement::bindValue
Пример:
$upload_user = $db_pdo->prepare('SELECT
K.value AS unit
FROM users AS O,
users_contacts AS K
WHERE O.user_id = :user_id
AND K.user_id = O.user_id
AND K.type = \'unit\'
AND K.value >= :unit_btm
AND K.value < :unit_top');
$upload_user->bindValue(':user_id', $user, PDO::PARAM_INT);
$upload_user->bindValue(':unit_btm', $user_unit_btm, PDO::PARAM_INT);
$upload_user->bindValue(':unit_top', $user_unit_top, PDO::PARAM_INT);
$upload_user->execute();
Альтернативой будетдля принудительного приведения типов данных к параметру в запросе.
$upload_user = $db_pdo->prepare('SELECT
K.value AS unit
FROM users AS O,
users_contacts AS K
WHERE O.user_id = :user_id
AND K.user_id = O.user_id
AND K.type = \'unit\'
AND K.value >= (:unit_btm - 0)
AND K.value < (:unit_top - 0)'); //CAST(:unit_top AS SIGNED)
$upload_user->execute([
':user_id' => $user,
':unit_btm' => $user_unit_btm,
':unit_top' => $user_unit_top
]);
Еще одним фактором, способствующим вашей проблеме, является то, что MySQL автоматически выполнит преобразование в тип данных столбца для сравнения.Если другие RDMBS, такие как PostgreSQL и SQLite3, не выполняют одинаковые преобразования.
Когда оператор используется с операндами различных типов, происходит преобразование типов для обеспечения совместимости операндов.Некоторые преобразования происходят неявно.Например, MySQL автоматически преобразует строки в числа по мере необходимости, и наоборот.
Источник: https://dev.mysql.com/doc/refman/5.7/en/type-conversion.html
Поскольку исходный тип данных столбца был VARCHAR
, это привело к следующему изваше тестирование.
DB Fiddle
Первоначальный запрос как PDOStatement::execute([1000])
.
SELECT IF('910' > '1000', 'fail', 'pass') AS if_str_to_str;
| if_str_to_str |
| ------------- |
| fail |
Вручную целое число для запроса
SELECT IF('910' > 1000, 'fail', 'pass') AS if_str_to_int;
| if_str_to_int |
| ------------- |
| pass |
После изменения типа данных столбца базы данных и использования PDOStatement::execute([1000])
SELECT IF(910 > '1000', 'fail', 'pass') AS if_int_to_str;
| if_int_to_str |
| ------------- |
| pass |
Использование PDOStatement::bindValue(':param', '1000', PDO::PARAM_INT)
или ('1000' - 0)
SELECT IF('910' > CAST('1000' AS SIGNED), 'fail', 'pass') AS if_str_to_typecast_int;
| if_str_to_typecast_int |
| ---------------------- |
| pass |