Обновите счетчик (поле) безопасно в SQL - PullRequest
5 голосов
/ 03 июня 2009

Я хочу реализовать ТАКИЕ теги на пост пользователя. У меня есть таблица с именем tag_data со столбцами tagId, title, count. У меня есть отдельная таблица, которая связывает отношения между публикацией и многими тегами, которые она может использовать.

Вот в чем проблема, как мне получить текущий счетчик, увеличить или уменьшить его на единицу и сохранить его БЕЗОПАСНО. Так что никакое другое соединение / поток не будет обновлять его между временем, когда я выбираю и обновляю?

Ответы [ 3 ]

13 голосов
/ 03 июня 2009

Полагаю, вам также нужен новый счетчик, в противном случае это не составляет никакого труда, просто обновите набор счетчиков = количество + 1.

Если ваша база данных поддерживает условие вывода в UPDATE (например, SQL Server 2K5 или 2K8):

UPDATE table
   SET count = count + 1
   OUTPUT inserted.count
   WHERE id=@id;

в противном случае:

begin transaction
update table 
    set counter=counter+1
    where id=@id;
select counter
    from table
    where id=@id;
commit;
0 голосов
/ 03 июня 2009

SET Count = Count + 1 - ИМХО самое простое решение ..

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

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

ИМХО, лучший подход - выбрать оптимистичный маршрут и обнаружить / повторить попытку, если в необычном случае что-то, о чем вы заботитесь, изменилось.

ВЫБРАТЬ СЧЕТ КАК СТАРЫЙ ... ОТ ...

.. обработка ...

ОБНОВЛЕНИЕ ... SET Count = oldplus1 WHERE Count = old AND ...

Если UPDATE не даст вам количество строк, которое, как вы ожидаете, вы предполагаете, что данные были изменены, и повторите попытку, пока это не удастся.

0 голосов
/ 03 июня 2009

псевдокод:

begin transaction
A = select count from tag_data where tagId = TagId
update tag_data set count = A+1 where tagId = TagId
commit
end transaction

Я настоятельно рекомендую создать хранимую процедуру, скажем, increment_tag(TagId), которая выполняет все вышеперечисленное:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...