È probabile che si tratti di logica aziendale, che probabilmente non appartiene al livello di archiviazione dei dati. Tuttavia, può comunque essere realizzato utilizzando trigger .
Puoi creare un BEFORE UPDATE
trigger che genera un errore se un record "bloccato" sta per essere aggiornato; poiché si verifica un errore prima l'operazione è stata eseguita, MySQL smette di procedere con essa. Se vuoi anche impedire l'eliminazione del record, devi creare un attivatore simile BEFORE DELETE
.
Per determinare se un record è "bloccato", puoi creare un locked
booleano colonna:
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 ...;
Tieni presente che SIGNAL
è stato introdotto in MySQL 5.5. Nelle versioni precedenti, è necessario eseguire alcune azioni errate che causano la generazione di un errore da parte di MySQL:spesso chiamo una procedura inesistente, ad es. con CALL raise_error;
Di nuovo, se devi assolutamente posizionare questa logica nel livello di archiviazione e non è possibile identificare i record bloccati con mezzi diversi dalla PK:potreste codificare il test nel trigger; ad esempio, per "bloccare" il record con 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 ;
Ma questo è assolutamente orribile e farei quasi tutto per evitarlo quando possibile.