Вероятно, мы могли бы достичь с помощью триггеров MySQL.
Мы должны рассмотреть вариант , а не , чтобы хранить счетчик на table_a
, а вместо этого просто получить счет от table_b
.
Есть также некоторые проблемы, о которых мы должны знать при реализации триггеров. Это может повлиять на производительность, а для триггеров, выполняющих DML, существует вероятность возникновения конфликта блокировок. Триггеры не бесплатны и не являются «волшебной пулей».
Нам нужен триггер AFTER UPDATE
(для обработки случаев, когда строка обновляется для изменения значения столбца code
), а также триггеры AFTER INSERT
и AFTER DELETE
.
Нам понадобится подходящий индекс для table_b, например,
ON table_a (code)
Предполагая, что столбец table_a counter
НЕ равен NULL и что counter
инициализируется ожидаемым значением.
Как первый срез:
- после удаления
DELIMITER $$
CREATE TRIGGER table_b_ad
AFTER DELETE ON table_b
FOR EACH ROW
BEGIN
-- decrement counter on row of table_a with matching OLD code
UPDATE table_a a
SET a.counter = a.counter - 1
WHERE a.code <=> OLD.code
;
END$$
DELIMITER ;
- после вставки
DELIMITER $$
CREATE TRIGGER table_b_ai
AFTER INSERT ON table_b
FOR EACH ROW
BEGIN
-- increment counter on row of table_a with matching NEW code
UPDATE table_a a
SET a.counter = a.counter + 1
WHERE a.code <=> NEW.code
;
END$$
DELIMITER ;
- после обновления
DELIMITER $$
CREATE TRIGGER table_b_au
AFTER UPDATE ON table_b
FOR EACH ROW
BEGIN
IF NOT ( NEW.code <=> OLD.code ) THEN
-- decrement counter on row of table_a that matches OLD code
UPDATE table_a a
SET a.counter = a.counter - 1
WHERE a.code <=> OLD.code
;
-- increment counter on row of table_a that matches NEW code
UPDATE table_a a
SET a.counter = a.counter + 1
WHERE a.code <=> NEW.code
;
END IF;
END$$
DELIMITER ;
Примечание:
В триггере MySQL,
NEW.code
относится к «новому» значению, назначенному столбцу code
с помощью инструкции INSERT или UPDATE.
OLD.code
относится к «старому» значению, которое было в столбце code
перед оператором UPDATE или DELETE.
<=>
(оператор космического корабля) - это оператор сравнения NULL-безопасный, возвращает либо TRUE, либо FALSE Не возвращает NULL, как это делает обычный оператор сравнения при сравнении значения NULL.
x <=> y
сокращенно эквивалентно письму ( x = y OR ( x IS NULL AND y IS NULL ) )
Цель для сравнения в триггере UPDATE состоит в том, что если значение code
не изменилось, нет необходимости проходить процедуру вычитания 1 из счетчика для этого значения code
, а затем немедленно добавив 1 к тому же счету. Более эффективно просто избегать ненужных операторов UPDATE.