Ответ 1
Вероятно, это бизнес-логика, которая, вероятно, не относится к вашему слоту хранения данных. Тем не менее, это может быть достигнуто с помощью триггеров.
Вы можете создать триггер BEFORE UPDATE
, который вызывает ошибку, если "заблокированная" запись будет обновлена; поскольку перед выполнением операции происходит ошибка, MySQL перестает ее выполнять. Если вы также хотите, чтобы запись не удалялась, вам нужно создать аналогичный триггер BEFORE DELETE
.
Чтобы определить, заблокирована ли запись, вы можете создать столбец boolean locked
:
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 ...;
Обратите внимание, что SIGNAL
был введен в MySQL 5.5. В более ранних версиях вы должны выполнить некоторые ошибочные действия, которые заставляют MySQL вызывать ошибку: я часто вызываю несуществующую процедуру, например. с CALL raise_error;
Я не могу создать дополнительный столбец в этой таблице, но строка имеет уникальный идентификатор в одном из столбцов, так как я могу сделать это для этого сценария?
Опять же, если вы абсолютно должны поместить эту логику на уровень хранения - и не можете идентифицировать заблокированные записи любыми способами, кроме PK, вы можете жестко закодировать тест в своем триггере; например, "заблокировать" запись с помощью 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 ;
Но это абсолютно ужасно, и я бы сделал почти все, чтобы избежать его, когда это возможно.