Ответ 1
попробуйте это
UPDATE `lastid` SET `idnum` = (SELECT `id` FROM `history` ORDER BY `id` DESC LIMIT 1);
выше код работал у меня
У меня есть таблица задач MySQL для выполнения, каждая строка имеет параметры для одной задачи.
Существует множество рабочих приложений (возможно, на разных компьютерах), выполняющих задачи в цикле.
Приложения получают доступ к базе данных с помощью API-интерфейсов API, основанных на MySQL.
Чтобы выполнить задачу, приложение делает что-то вроде этого:
Создайте глобально уникальный идентификатор (для простоты, допустим, это число)
UPDATE tasks
SET guid = %d
WHERE guid = 0 LIMIT 1
SELECT params
FROM tasks
WHERE guid = %d
Если последний запрос возвращает строку, мы владеем ею и имеем параметры для запуска
Есть ли способ добиться такого же эффекта (т.е. "собственный" ряд и получить его параметры) в одном вызове на сервер?
попробуйте это
UPDATE `lastid` SET `idnum` = (SELECT `id` FROM `history` ORDER BY `id` DESC LIMIT 1);
выше код работал у меня
Вы можете создать процедуру, которая делает это:
CREATE PROCEDURE prc_get_task (in_guid BINARY(16), OUT out_params VARCHAR(200))
BEGIN
DECLARE task_id INT;
SELECT id, out_params
INTO task_id, out_params
FROM tasks
WHERE guid = 0
LIMIT 1
FOR UPDATE;
UPDATE task
SET guid = in_guid
WHERE id = task_id;
END;
BEGIN TRANSACTION;
CALL prc_get_task(@guid, @params);
COMMIT;
Если вы ищете один запрос, тогда этого не может быть. Функция UPDATE возвращает только количество обновленных элементов. Аналогично, функция SELECT не изменяет таблицу, а возвращает только значения.
Использование процедуры действительно превратит ее в одну функцию, и это может быть удобно, если блокировка является для вас проблемой. Если ваша самая большая проблема связана с сетевым трафиком (то есть: передача слишком большого количества запросов), используйте эту процедуру. Если вы беспокоитесь о перегрузке сервера (то есть: DB работает слишком усердно), то дополнительные накладные расходы процедуры могут ухудшить ситуацию.
Я не знаю об одной части вызова, но то, что вы описываете, является блокировкой. Замки являются важным элементом реляционных баз данных.
Я не знаю специфики блокировки строки, ее чтения, а затем ее обновления в MySQL, но с небольшим чтением mysql заблокировать документацию, вы можете делать всевозможные манипуляции с блокировкой.
У публикации postgres locks есть отличный пример, описывающий то, что вы хотите сделать: заблокируйте таблицу, прочитайте таблицу, измените таблица.
UPDATE tasks
SET guid = %d, params = @params := params
WHERE guid = 0 LIMIT 1;
Он вернет 1 или 0, в зависимости от того, были ли значения эффективно изменены.
SELECT @params AS params;
Это просто выбирает переменную из соединения.
От: здесь
У меня такая же проблема. Вместо этого мы использовали PostreSQL и UPDATE ... RETURNING
:
Дополнительное предложение RETURNING заставляет UPDATE вычислять и возвращать значения (значения) на основе каждой реально обновленной строки. Любое выражение, использующее столбцы таблицы и/или столбцы других таблиц, упомянутых в FROM, может быть вычислено. Используются новые (пост-обновления) значения столбцов таблицы. Синтаксис списка RETURNING идентичен синтаксису выходного списка SELECT.
Пример: UPDATE 'my_table' SET 'status' = 1 WHERE 'status' = 0 LIMIT 1 RETURNING *;
Или, в вашем случае: UPDATE 'tasks' SET 'guid' = %d WHERE 'guid' = 0 LIMIT 1 RETURNING 'params';
Извините, я знаю, что это не отвечает на вопрос с MySQL, и было бы непросто просто переключиться на PostgreSQL, но это лучший способ, который мы нашли для этого. Еще через 6 лет MySQL по-прежнему не поддерживает UPDATE ... RETURNING
. Он может быть добавлен в какой-то момент в будущем, но на данный момент MariaDB имеет только для операторов DELETE.
Изменить. Задача (низкий приоритет) - добавить UPDATE ... RETURNING
поддержку MariaDB.