Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment définir une ligne MySQL en LECTURE SEULE ?

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.