Сделать столбец неизбежным в MySQL
-
16-10-2019 - |
Вопрос
Я хочу сделать столбец в отношениях, немодифицированном по причинам последовательности.
Предыстория заключается в том, что у меня есть отношения: n, где отношение «соединения» имеет дополнительные значения. Я не хочу, чтобы кто -то мог изменить идентификаторы партнеров по отношениям.
Что я придумал до сих пор:
Создание триггера, который проверяет, такое новое значение такого же, как старое значение. Но я не знаю, как отрицать действие обновления, если условие оказалось как истинное.
Вот мой триггер до сих пор:
CREATE TRIGGER deny_nton_change BEFORE UPDATE ON Schueler_in_Klasse
FOR EACH ROW BEGIN
IF NEW.Schueler_ID != OLD.Schueler_ID OR NEW.Klasse_ID != OLD.Klasse_ID THEN
END IF;
END;
Решение
Вместо того, чтобы прервать обновление, просто переопределите его?
...
FOR EACH ROW BEGIN
SET NEW.Schueler_ID = OLD.Schueler_ID;
SET NEW.Klasse_ID = OLD.Klasse_ID;
END
Другие советы
Довольно хороший и чистый способ прервать и вернуть читаемое сообщение об ошибке, используя сигнал:
Сигнал sqlstate '45000' set message_text = 'schueler_id и klasse_id не может быть изменена!';
Убедитесь, что ваша версия MySQL поддерживает это, она была введена в MySQL 5.5. В более ранних версиях вам нужны взломы, такие как вставка не существующего поля в не существующую таблицу.
Как упоминает GBN, перезапись новых значений со старыми также является хорошим вариантом.
Я на самом деле научился обратно-задумчивому подходу к абортированию триггеров. Анкет Это очень грубое, но работает, потому что обработка сигнала не реализована на языке хранимой процедуры MySQL. Это может быть в лучшем случае эмулировать.
Глава 11, страницы 254-256 книги MySQL хранящаяся процедура Программирование под подзаголовом 'Проверка данных с помощью триггеров' предлагает сделать выбор строки символов в фиктивное целое число (с точки зрения синтаксиса, это правильно, но умирает от исполнения [без каламбура]):
CREATE TRIGGER deny_nton_change BEFORE UPDATE ON Schueler_in_Klasse
FOR EACH ROW BEGIN
DECLARE dummy INT;
IF NEW.Schueler_ID != OLD.Schueler_ID OR NEW.Klasse_ID != OLD.Klasse_ID THEN
SELECT 'Cannot Carry Out This Trigger Any Further'
INTO dummy FROM table_you_know_does_not_exist WHERE 1=1 LIMIT 1;
END IF;
END;
На самом деле можно сделать это аккуратно без использования триггеров, если вы используете InnoDB.
Создайте другую таблицу с одним столбцом. Этот столбец должен иметь внешний ключ (отсюда и требование InnoDB в этом решении), который указывает на неизменную столбец исходной таблицы.
Поместите ограничение, как «Ограничение обновления».
В итоге:
CREATE TABLE original (
....
immutable_column ...
INDEX index1(immutable_column)
....
) ENGINE=INNODB;
CREATE TABLE restricter (
.....
col1,
INDEX index2(col1),
FOREIGN KEY (col1) REFERENCES original (immutable_colum) ON UPDATE RESTRICT ON DELETE CASCADE
) ENGINE=INNODB;
Основываясь на комбинации всех ответов, которые я прочитал, это то, что сработало для меня:
delimiter $$ -- You may need this or not (in my visual client I need it, directly in console I don't)
create trigger deny_nton_change before update on surveys
for each row begin
if new.Schueler_ID != old.Schueler_ID OR new.Klasse_ID != old.Klasse_ID then
signal sqlstate '45000' set message_text = 'My own Error: Field is immutable';
end if;
end$$
delimiter ; -- You may need this or not