Питання Як встановити рядок MySQL в "READ-ONLY"?


У мене є ряд в таблиці, який я не хочу бути змінений (колись).

Чи можна встановити рядок MySQL на "READ-ONLY", щоб його не можна оновлювати будь-яким способом? Якщо так, то як?

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

Дякую.


32
2018-05-08 16:09


походження


Ні, таке поняття, як рядок для читання, не існує. Але ви можете налаштувати облікові записи MySQL таким чином, що певний користувач не має прав на оновлення / видалення. - Marc B
Позиція: stackoverflow.com/questions/3878672/... - Kris.Mitchell
@Marc B: Отже, ні один з варіантів, про які я згадав, доступний? Будь ласка, підтвердіть, тому що рішення, яке ви дозволили користувачеві, не вирішить мою проблему на жаль. - ProgrammerGirl
@ Крис: не дублікат цього питання взагалі. Моє питання абсолютно інше. - ProgrammerGirl
@ Рахул: Мені потрібно оновити інші рядки в таблиці, тому це не варіант. - ProgrammerGirl


Відповіді:


Ймовірно, це бізнес-логіка, яка, ймовірно, не належить до вашого сховища даних. Тим не менш, це може бути досягнуте завдяки використанню тригери.

Ви можете створити a BEFORE UPDATE тригер, який викликає помилку, коли "заблокований" запис буде оновлено; оскільки виникає помилка раніше операція виконується, MySQL перестає продовжувати його. Якщо ви також хочете запобігти видаленню запису, вам потрібно створити подібний тригер BEFORE DELETE.

Щоб визначити, чи запис "заблокований", ви можете створити логічний 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-you міг жорсткий код тесту в ваш тригер; наприклад, "заблокувати" запис із 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 ;

Але це так абсолютно жахливо і я б це зробив майже що завгодно щоб уникнути цього, коли це можливо.


36
2018-05-08 16:12



Дякую за дуже цікаве рішення. Я не можу створити додатковий стовпець у цій таблиці, але рядок має унікальний ідентифікатор в одному з стовпців, так як я можу зробити це для цього сценарію? - ProgrammerGirl
@Programmer: Просто перевірте це id в IF виклад тригера: IF OLD.column <=> 'unique_id' THEN .... - eggyal
Тепер існує нестандартне рішення. Мені це подобається. +1, майте на увазі, що у вас може бути тільки один тригер (за подію на кожну таблицю) в mysql, так що якщо у вас вже є або потрібно ще один тригер у майбутньому ... вам доведеться об'єднати їх у один. - Kris
@eggyal: ОК. Три питання: 1) Що таке "<=>"? 2) Що таке "СТАРИЙ"? 3) Що таке "DELIMITER ;;" ? Знову дякую! - ProgrammerGirl
@ Програміст: <=>є NULLбезпечний оператор порівняння рівності; OLD і NEW ключові слова доступні в тригері, які надають доступ до значень зачеплених записів до / після операції - див Сигнальний тригер; DELIMITER вказує новий роздільник оператора, щоб команди, які самі містять звичайні ; роздільники розглядаються як єдине твердження - ви можете обрати символьні послідовності, відмінних від ;; якщо ви віддаєте перевагу. - eggyal