É provável que seja lógica de negócios, que provavelmente não pertence à sua camada de armazenamento de dados. No entanto, isso pode ser feito usando triggers .
Você pode criar um
BEFORE UPDATE
gatilho que gera um erro se um registro "bloqueado" estiver prestes a ser atualizado; uma vez que ocorre um erro antes a operação é realizada, o MySQL deixa de prosseguir com ela. Se você também quiser evitar que o registro seja excluído, será necessário criar um gatilho semelhante BEFORE DELETE
. Para determinar se um registro está "bloqueado", você pode criar um booleano
locked
coluna: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 ...;
Observe que
SIGNAL
foi introduzido no MySQL 5.5. Nas versões anteriores, você deve executar alguma ação errônea que faça com que o MySQL gere um erro:Eu frequentemente chamo um procedimento inexistente, por exemplo. com CALL raise_error;
Novamente, se você absolutamente deve colocar essa lógica na camada de armazenamento - e não pode identificar os registros bloqueados por nenhum outro meio que não seja o PK - você poderia codifique o teste em seu gatilho; por exemplo, para "bloquear" o registro com
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 ;
Mas isso é absolutamente horrível e eu faria quase tudo para evitá-lo sempre que possível.