Чат Telegram
Группа ВКонтакте

СУБД считает недопустимыми поступающие в неё данные

Помогите, люди добрые. Ошибка сводит с ума.

Ошибка работает только на локальном сервере XAMPP с СУБД MariaDB. На рабочий сервер пока ничего не выкладывал, так как работа пока ещё далека от завершения.

Есть база данных с таблицей calendar, в которой присутствует одна-единственная колонка date (тип данных DATE). И есть вот такой php-код, которой выполняется при каждом запуске скрипта и, как видно из этого кода, должен просто добавлять в таблицу calendar очередные записи, если максимальная дата в calendar отстоит от сегодняшнего дня менее чем на 700 дней. И запрос данных из БД, и отправка туда новой записи делаются с помощью PDO.

$stm = $dbh->prepare("SELECT * FROM `calendar` ORDER BY date DESC LIMIT 1 ");
$stm->execute();
$maxDateFromDB = $stm->fetchAll();
if (time() + (700*24*60*60) > strtotime($maxDateFromDB[0]['date'])) {
    $stm = $dbh->prepare("INSERT INTO `calendar`(date) VALUES (':newdate')");
    $stm->bindValue('newdate', date("Y-m-d", strtotime($maxDateFromDB[0]['date']) + (24*60*60)));
    $stm->execute();
}

Проблема в том, что MariaDB считает поступающие в неё из этого скрипта value недопустимыми и пытается записывать их в таблицу как 0000-00-00 (что, разумеется, у неё не получается, так как date, будучи единственным полем в таблице, вынуждено по совместительству быть ещё и уникальным).

При этом, если из кода убрать строку $stm->bindValue, а в инструкции INSERT в VALUE написать любую реальную дату, например

INSERT INTO `calendar`(date) VALUES ('2020-10-30'),

то код отлично отработает.

При этом код

date("Y-m-d", strtotime($maxDateFromDB[0]['date']) + (24*60*60))

, как показали многочисленные исследования, совершенно корректно генерирует нужные значения VALUE. Вывод этого кода в переменную, с дальнейшей подстановкой в bindValue, к сожалению, не решает проблемы.

Загадочная предыстория.
Дело в том, что данный код был написан мною пару дней назад, и эту пару дней он прекрасно поработал, наполнив таблицу calendar записями на пол года вперёд. Однако, при этом он выглядел несколько иначе. Пятая строка выглядела так:

$stm = $dbh->prepare('INSERT INTO `calendar`(date) VALUES (:newdate)');

т. е. вокруг плэйсхолдера :newdate не было кавычек, а сама SQL-инструкция была обрамлена не двойными кавычками, а одинарными. Однако сегодня вечером, совершенно внезапно, без объявления войны, этот код перестал работать (MariaDB стала считать все поступающие из скрипта значения недопустимыми). Я сделал экспериментальную таблицу точно такого же формата, но и в ней такие такие INSERT приводили к точно таким же последствиям. Недолгий поиск по учебникам подсказал мне, что синтаксически более правильным является указание значения VALUES в кавычках. Ну я переписал SQL-инструкцию. На уровне phpMyAdmin всё заработало. Но то, что поступает из скрипта, MariaDB продолжает пытаться запихивать в таблицу как 0000-00-00.

Maxim 19.05.2020 в 18:16

Ответы на вопрос (4)


В общем, подобрал решение. Вывожу числовое значение в переменную, а затем переменную использую в качестве параметра функции execute, в обход bindValue. Т.е. вместо

$stm = $dbh->prepare("INSERT INTO `calendar`(date) VALUES (':newdate')");
$stm->bindValue('newdate', date("Y-m-d", strtotime($maxDateFromDB[0]['date']) + (24*60*60)));
$stm->execute();

пишу

$newdate = date("Y-m-d", strtotime($maxDateFromDB[0]['date']) + (24*60*60));
$stm = $dbh->prepare("INSERT INTO `calendar`(date) VALUES (?)");
$stm->execute(array($newdate));

При этом, что очень странно, если указывать VALUES ('?'), то не работает. Ни ошибку ни даёт, ни записи ни создаёт. Работает только вот так, без кавычек. Но почему именно так, и почему вчера работал код с bindValue, а сегодня не работает - для меня остаётся загадками.

Maxim 19.05.2020 в 20:12

И без переменной тоже работает

$stm = $dbh->prepare("INSERT INTO `calendar`(date) VALUES (?)");
$stm->execute(array(date("Y-m-d", strtotime($maxDateFromDB[0]['date']) + (24*60*60))));
Maxim 19.05.2020 в 20:13

Попробовал на сервере с MySQL. Точно такая же байда как с MariaDB. Один в один.

$stm = $dbh->prepare("INSERT INTO `calendar`(date) VALUES (':newdate')");
$stm->bindValue('newdate', date("Y-m-d", strtotime($maxDateFromDB[0]['date']) + (24*60*60)));
$stm->execute();

не работает

$stm = $dbh->prepare("INSERT INTO `calendar`(date) VALUES (?)");
$stm->execute(array(date("Y-m-d", strtotime($maxDateFromDB[0]['date']) + (24*60*60))));

работает

Maxim 19.05.2020 в 20:35

$stm->bindValue(':newdate'...

и используйте новый синтаксис для массивов. [] а не array().

ivashkevich 21.05.2020 в 07:22

Добавить новый ответ