Intereting Posts
Можно ли написать парсер электронной почты в PHP? Как сделать запрос HTTPS с помощью cURL? Как использовать подпапку в маршруте контроллера по умолчанию в CodeIgniter 3 Массовое назначение Laravel не заполняет поля PDO Prepared Вставляет несколько строк в один запрос Можно ли отправить форму флага без кнопки отправки в php? Передача нескольких элементов флажка в файл PHP с использованием JSON и запрос к базе данных php рендеринг большого zip-файла – достигнут предел памяти Ошибка «Только оригинальный поток, создавший иерархию представлений, может коснуться его представлений» в Android Слэш добавлен ко всем моим сообщениям Обнаружение, если изображение встроено Как я могу поместить внутренний тег в другое положение? Как проверить, существует ли элемент с SimpleXML? PHP (WAMP) – Exlipse PDT, xDebug: не останавливается в точке останова Расширение класса Validator в Laravel

Странное поведение с mysql_affected_rows () в PHP

У меня есть таблица с именем user_ips чтобы отслеживать пользователей в случае удаления их файлов cookie или изменения браузера. Так или иначе, следующий код прост. Он обновляет записи в user_ips, которые равны идентификатору пользователя и IP. Если запрос не обновил строки, это значит, что IP для этого пользователя отсутствует в таблице, поэтому он вставляет его.

 $site->query('UPDATE `user_ips` SET `last_time` = UNIX_TIMESTAMP(), `user_agent` = \''.$this->user_agent.'\' WHERE `ip` = '.$this->ip.' AND `userid` = '.$this->id); if(mysql_affected_rows() == 0) { $site->query('INSERT INTO `user_ips` SET `userid` = '.$this->id.', `ip` = '.$this->ip.', `first_time` = UNIX_TIMESTAMP(), `last_time` = UNIX_TIMESTAMP(), `user_agent` = \''.$this->user_agent.'\''); } 

Проблема заключается в том, что mysql_affected_rows () иногда возвращает 0, даже если существует строка с текущим идентификатором и IP-адресом пользователя. Таким образом, код добавляет еще одну строку в таблицу с тем же IP-адресом.

В случае, если вам интересно, $ site – это класс mysql, который я сделал для моего сайта, и единственным запросом, который он выполняет, является тот, который он передал с помощью query (), и ничего больше, так что это не проблема с классом. Ох, и IP хранится как длинный IP-адрес, поэтому ему не нужны кавычки.

Я прямо цитирую PHP-документацию здесь:

При использовании UPDATE MySQL не будет обновлять столбцы, где новое значение совпадает со старым значением. Это создает вероятность того, что mysql_affected_rows () может фактически не равняться количеству согласованных строк, а только количеству строк, которые были буквально затронуты запросом.

Поэтому в вашем случае mysql_affected_rows () вернет 0, когда UNIX_TIMESTAMP () возвращает одно и то же значение (например, два запроса от одного и того же клиента за одну секунду).

Чтобы построить ответ slipbull, самым простым способом справиться с этим является, возможно, просто выполнить запрос SELECT для оценки того, нужен ли INSERT. Другим решением было бы просто ВСТАВИТЬ запись при создании пользователя, так как это гарантировало бы действительную запись.

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

Другим вариантом может быть использование команды MySQL REPLACE. http://dev.mysql.com/doc/refman/5.0/en/replace.html . Которая удалит строку, если она уже существует, а затем вставьте строку.

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