Обновление поля, на котором основан цикл запроса Select

Это грубый пример моего запроса mysql (примечание: это внутри другого цикла, который проходит через всех пользователей):

$query = db.query('SELECT * FROM table WHERE userid = $uid AND reminded = 0');

while ($row = $query->fetch()) {
  // send personalized reminder email to the user
  db.query('UPDATE table SET reminded = 1 WHERE userid = $uid');
}

В поле reminded установлено значение 1 для всех экземпляров для этого пользователя.

Мой вопрос: Загружен ли запрос/пока (выборка) в память на основе исходных условий (reminded = 0) или оставшийся цикл while будет вести себя в соответствии с этими обновлениями (reminded = 1)?

Допустим, у пользователя было 50 строк, где reminded равно 0, и запрос выбирает их: они все еще существуют со значением 0 в остальной части цикла while, даже если все они были изменены на 1 во время цикла?

Не уверен, что вы пытаетесь сделать, но, судя по всему, это может стать 1 запросом.

Naruto 14.03.2019 14:36

не смешивайте mysql с php. Как только вы запустите первый запрос, вы перенесете данные из mysql в php. Затем вы запускаете цикл обновления через массив php. В результате, если выбрать извлечение 50 записей, вы запустите обновление 50 раз. Вкратце: ответ на ваш вопрос «Да»

Lelio Faieta 14.03.2019 14:36

@LelioFaieta Ах да, хорошо, это имеет смысл. Теперь я вижу это немного яснее. Итак, я не могу изменить то, что содержит цикл запроса после его загрузки?

mowgli 14.03.2019 14:37

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

Lelio Faieta 14.03.2019 14:39

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

Raymond Nijland 14.03.2019 14:40

@LelioFaieta Сценарий: у пользователя есть 10 непрочитанных сообщений (напоминается = 0). Я хочу просмотреть их и напомнить пользователю ОДИН раз и установить напоминание = 1 для всех остальных сообщений и игнорировать их, чтобы он/она не получал более одного напоминания.

mowgli 14.03.2019 14:41

Ваш запрос UPDATE уже делает это. Просто запустите это (один раз). Вы можете добавить AND reminded = 0 в конце, чтобы более точно ориентироваться только на точные строки (хотя это не будет иметь большого значения, если вы обновите другие строки до значения, которое у них уже есть, но этот пункт делает его строго более правильным). Вам не нужен SELECT, если только он не имеет другой отдельной цели (например, вы хотите заранее отобразить данные на экране или что-то в этом роде).

ADyson 14.03.2019 14:42

затем переместите обновление из цикла. Прикрепите его к событию отображения сообщений

Lelio Faieta 14.03.2019 14:42

Как @ADyson также сказал, что использование UPDATE table SET reminded = 1 WHERE userid = $uid AND reminded = 0 должно делать то же самое. Также остерегайтесь SQL-инъекций в свой код.

Raymond Nijland 14.03.2019 14:43

@ADyson я предполагаю, что выбор должен отображать сообщения (вот почему цикл). Обновление должно быть привязано к событию, например, по клику для отображения.

Lelio Faieta 14.03.2019 14:43

Код представляет собой очень грубый пример того, как выглядит мой код для отправителя напоминаний по электронной почте. Он должен проходить без напоминаний и напоминать только ОДИН раз о ЛЮБЫХ непрочитанных сообщениях. Черт, это трудно объяснить ;) но, думаю, это помогает мне лучше понять, чего я хочу.

mowgli 14.03.2019 14:45

«Он должен проходить без напоминания»… нет, ему вообще не нужно перебирать их в цикле (если только вам не нужно сначала показать их на экране или выполнить какую-либо другую несвязанную обработку строк). Это наша точка зрения. Для того, чтобы установить для поля «напоминание» значение 1 для всех сообщений без напоминаний, вашего запроса UPDATE уже достаточно — он будет работать с этими строками все в одном операторе. В этом прелесть структуры команд SQL, основанной на наборах. Возможно, вам может понадобиться выбрать первое ненапоминаемое письмо и отправить напоминание о нем, но вам, конечно, не нужно выбирать все из них для этого

ADyson 14.03.2019 14:47

@ADyson Мне нужен цикл для выполнения других действий и отправки напоминания каждому пользователю (это для задания cron). Может быть, мне просто нужно перепроверить для каждой итерации, было ли отправлено какое-либо напоминание этому пользователю, и пропустить отправку, если это так

mowgli 14.03.2019 14:50

«отправка напоминания каждому пользователю» ... ваш цикл относится к одному пользователю (оператор SQL SELECT выбирает идентификатор пользователя). Возможно, у вас есть цикл разные для проверки каждого пользователя, но вам не нужен показанный здесь цикл, если только вы не можете уточнить, что такое «другие вещи».

ADyson 14.03.2019 14:51

@ADyson Ах да, извините. Этот цикл находится внутри другого цикла, который проходит через каждого пользователя. Я ценю вашу помощь, я думаю, что я ближе к тому, как я могу это сделать

mowgli 14.03.2019 14:52
SELECT * FROM table WHERE userid = $uid AND reminded = 0 LIMIT 1 вы получите первое ненапоминаемое сообщение для этого пользователя. Затем просто выберите эту единственную строку из результатов и используйте ее для создания электронного письма. После этого запустите UPDATE table SET reminded = 1 WHERE userid = $uid AND reminded = 0 один раз в конце.
ADyson 14.03.2019 14:55
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
16
50
1

Ответы 1

Предполагая, что код и SQL, которые у вас есть, являются только примером (потому что вы должны обновлять напрямую без цикла php).

Выборка строк table выполняется в БД построчно.

Итак, если одна или несколько из этих строк обновляются в цикле while, в следующих итерациях вы будете извлекать и обновлять (снова) предыдущие обновленные строки.

Я думаю, что вы должны быть осторожны «только», если вы обновляете поле, которое является частью индекса, или поле, которое используется в SQL для извлечения данных (например, поле, используемое в ORDER BY и т. д.).

«Я думаю, что вы должны быть осторожны «только», если вы обновляете поле, которое является частью индекса, или поле, которое используется в SQL для извлечения данных (например, поле, используемое в ORDER BY и т. д.) ." Да, если вы не хотите перестраивать индекс после каждого UPDATE, вы должны использовать транзакцию и зафиксировать ее.
Raymond Nijland 14.03.2019 14:49

Другие вопросы по теме