Fare un immutabile di colonna in MySQL
-
16-10-2019 - |
Domanda
Voglio fare una colonna in un rapporto unmodifyable per motivi di coerenza.
Il retroscena è che ho un n: n rapporto in cui la relazione "collegamento" ha valori aggiuntivi. Non voglio che chiunque è in grado di cambiare gli ID dei partner di relazione.
Quello che ho messo a punto finora:
La creazione di un trigger che controlla se il nuovo valore è uguale al vecchio valore. Ma io non so come negare l'azione UPDATE se la condizione si rivela come VERO.
Ecco il mio grilletto finora:
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;
Soluzione
Piuttosto che abortire l'aggiornamento, basta ignorare vero?
...
FOR EACH ROW BEGIN
SET NEW.Schueler_ID = OLD.Schueler_ID;
SET NEW.Klasse_ID = OLD.Klasse_ID;
END
Altri suggerimenti
Un modo abbastanza bello e pulito per annullare e restituire un messaggio di errore leggibile è quello di utilizzare un segnale:
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Schueler_ID e Klasse_ID non possono essere modificate!';
Facciamo in modo la versione di MySQL sostiene questo, è stato introdotto in MySQL 5.5. Nelle versioni precedenti è necessario hack come l'inserimento di un campo inesistente in una tabella inesistente.
Come gbn menziona, sovrascrivendo i nuovi valori con quelli vecchi è una buona opzione troppo.
realtà ho imparato un approccio back-vicolo per abortire trigger . E 'molto grezzo, ma funziona perché l'elaborazione del segnale non è implementata in stored procedure Lingua di MySQL. Si può essere emulato al meglio.
Capitolo 11, pagine 254-256 del libro MySQL Stored Procedura di programmazione il sottotitolo 'dati Convalida con trigger' suggerisce fare un SELECT di una stringa di caratteri in un intero fittizio (in termini di sintassi, è corretto, ma stampi sullo esecuzione [NO gioco di parole]):
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;
In realtà è possibile farlo ordinatamente senza l'utilizzo di trigger se si utilizza InnoDB.
Crea un altro tavolo con una sola colonna. Tale colonna deve avere una chiave esterna (qui la necessità innodb in questa soluzione) che punta alla colonna immutabile della tabella originale in questione.
Mettere una restrizione del tipo "ON UPDATE Vieta".
In sintesi:
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;
In base a una combinazione di tutte le risposte che ho letto questo è ciò che ha funzionato per me:
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