Подтвердить что ты не робот

Как установить строку MySQL только для чтения?

У меня есть строка в таблице, которую я не хочу менять (когда-либо).

Можно ли установить строку MySQL в READ-ONLY, чтобы она не могла быть обновлена ​​каким-либо образом? Если да, то как?

Если нет, можно ли установить постоянное значение в одном из столбцов этой строки, чтобы его нельзя было изменить? Если да, то как?

Спасибо.

4b9b3361

Ответ 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 ;

Но это абсолютно ужасно, и я бы сделал почти все, чтобы избежать его, когда это возможно.