Я создал запрос, и мне интересно, будет ли он работать на любой базе данных, кроме MySQL.На самом деле я никогда не использовал другую базу данных, поэтому меня не устраивают различия.
UPDATE `locks` AS `l1`
CROSS JOIN (SELECT SUM(`value`) AS `sum` FROM `locks`
WHERE `key` IN ("key3","key2")) AS `l2`
SET `l1`.`value` = `l1`.`value` + 1
WHERE `l1`.`key` = "key1" AND (`l2`.`sum` < 1);
Вот некоторые особенности, на которые я полагаюсь (насколько я могу думать о них):
- Запросы на обновление.
- Включение в запросы на обновление.
- Агрегирование функций в запросах, не сгруппированных явно.
- ГДЕ ...В состоянии.
Я уверен, что людям будет любопытно, что именно это делает, и это может также включать функции базы данных, которые могут быть не повсеместными.Это реализация взаимного исключения с использованием базы данных, предназначенной для веб-приложения.В моем случае это было необходимо, потому что определенные действия пользователя приводят к удалению и воссозданию таблиц с разными столбцами, и я хочу избежать ошибок, если другие части приложения пытаются вставить данные.Поэтому реализация специализирована для решения проблемы читателей-писателей .
. В этом запросе предполагается, что существует таблица locks
с двумя полями: key
(varchar) и value
(int).Далее предполагается, что таблица содержит строку, такую, что key
= "key1".Затем он пытается увеличить value
для «key1».Это происходит только в том случае, если для каждого key
в списке ("key2","key3")
связанный value
равен 0 (условие WHERE для l2
является приближением, в котором value
никогда не бывает отрицательным).Поэтому этот запрос «получает блокировку» только при соблюдении определенных условий, предположительно атомарным способом.Затем приложение проверяет, получило ли оно блокировку по возвращаемому значению запроса, которое предположительно указывает, сколько строк было затронуто.Если и только если ни одна строка не была затронута, приложение не получило блокировку.
Итак, вот дополнительные условия, не различимые в самом запросе:
- Предполагается, что вВ многопоточной среде, копия этого запроса никогда не будет чередоваться с другой копией.
- При обработке запроса должно быть возвращено, были ли затронуты какие-либо значения.
В качестве вторичного запроса ябыл бы признателен за любые ресурсы по "стандартному SQL".Я слышал об этом, но так и не смог найти какое-либо определение, и мне кажется, что мне не хватает многих вещей, когда в документации MySQL говорится, что «эта функция является расширением стандартного SQL».
Основываясь на ответах, этот запрос должен работать лучше во всех системах:
UPDATE locks AS l1
CROSS JOIN (SELECT SUM(val) AS others FROM locks
WHERE keyname IN ('key3','key2')) AS l2
SET l1.val = l1.val + 1
WHERE l1.keyname = 'key1' AND (l2.others < 1);
Upvotes для всех из-за хороших ответов.Отмеченный ответ направлен на прямой ответ на мой вопрос, даже если он предназначен только для одной другой СУБД, и хотя могут быть лучшие решения для моей конкретной проблемы (или даже проблемы кросс-платформенного SQL в целом).