Prawdopodobnie jest to logika biznesowa, która prawdopodobnie nie należy do warstwy przechowywania danych. Niemniej jednak można to osiągnąć za pomocą wyzwalaczy .
Możesz utworzyć BEFORE UPDATE
wyzwalacz, który zgłasza błąd, jeśli „zablokowany” rekord ma zostać zaktualizowany; ponieważ błąd występuje przed operacja zostaje podjęta, MySQL przestaje ją wykonywać. Jeśli chcesz również zapobiec usunięciu rekordu, musisz utworzyć podobny wyzwalacz BEFORE DELETE
.
Aby określić, czy rekord jest „zablokowany”, możesz utworzyć wartość logiczną locked
kolumna:
ALTER TABLE my_table ADD COLUMN locked BOOLEAN NOT NULL DEFAULT FALSE;
DELIMITER ;;
CREATE TRIGGER foo_upd BEFORE UPDATE ON my_table FOR EACH ROW
IF OLD.locked THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot update locked record';
END IF;;
CREATE TRIGGER foo_del BEFORE DELETE ON my_table FOR EACH ROW
IF OLD.locked THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot delete locked record';
END IF;;
DELIMITER ;
UPDATE my_table SET locked = TRUE WHERE ...;
Pamiętaj, że SIGNAL
został wprowadzony w MySQL 5.5. We wcześniejszych wersjach trzeba wykonać jakąś błędną akcję, która powoduje, że MySQL zgłasza błąd:często wywołuję nieistniejącą procedurę, np. z CALL raise_error;
Ponownie, jeśli absolutnie musisz umieść tę logikę w warstwie przechowywania — i nie możesz zidentyfikować zablokowanych rekordów w żaden inny sposób niż PK — możesz zakoduj test na stałe w swoim wyzwalaczu; na przykład, aby „zablokować” rekord za pomocą id_column = 1234
:
DELIMITER ;;
CREATE TRIGGER foo_upd BEFORE UPDATE ON my_table FOR EACH ROW
IF OLD.id_column <=> 1234 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot update locked record';
END IF;;
CREATE TRIGGER foo_del BEFORE DELETE ON my_table FOR EACH ROW
IF OLD.id_column <=> 1234 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot delete locked record';
END IF;;
DELIMITER ;
Ale to absolutnie okropne i zrobiłbym prawie wszystko aby tego uniknąć, gdy tylko jest to możliwe.