Il s'agit probablement d'une logique métier, qui n'appartient probablement pas à votre couche de stockage de données. Cependant, cela peut néanmoins être accompli en utilisant des déclencheurs .
Vous pouvez créer un BEFORE UPDATE
déclencheur qui génère une erreur si un enregistrement "verrouillé" est sur le point d'être mis à jour ; puisqu'une erreur s'est produite avant l'opération est entreprise, MySQL cesse de la poursuivre. Si vous souhaitez également empêcher la suppression de l'enregistrement, vous devez créer un déclencheur similaire BEFORE DELETE
.
Pour déterminer si un enregistrement est "verrouillé", vous pouvez créer un booléen locked
colonne :
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 ...;
Notez que SIGNAL
a été introduit dans MySQL 5.5. Dans les versions antérieures, vous devez effectuer une action erronée qui amène MySQL à générer une erreur :j'appelle souvent une procédure inexistante, par ex. avec CALL raise_error;
Encore une fois, si vous le devez absolument placez cette logique dans la couche de stockage - et ne pouvez pas identifier les enregistrements verrouillés par d'autres moyens que le PK - vous pourriez codez le test en dur dans votre déclencheur ; par exemple, pour "verrouiller" l'enregistrement avec 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 ;
Mais c'est absolument horrible et je ferais presque n'importe quoi pour l'éviter autant que possible.