Frage

Ich möchte eine Spalte in einer Beziehung aus Konsistenzgründen unmodifizierbar machen.

Die Hintergrundgeschichte ist, dass ich eine: n Beziehung habe, in der die "Verbindungs" -Relation zusätzliche Werte hat. Ich möchte nicht, dass jemand die IDs der Beziehungspartner ändern kann.

Was ich mir bisher ausgedacht habe:

Erstellen eines Auslösers, der überprüft, ob der neue Wert dem alten Wert entspricht. Aber ich weiß nicht, wie ich die Aktualisierungsaktion ablehnen kann, wenn sich die Bedingung als wahr erweist.

Hier ist mein bisheriger Abzug:

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;
War es hilfreich?

Lösung

Anstatt das Update abzutrennen, außer Kraft setzen, überschreiben Sie es einfach?

...
FOR EACH ROW BEGIN
    SET NEW.Schueler_ID = OLD.Schueler_ID;
    SET NEW.Klasse_ID = OLD.Klasse_ID;
END

Andere Tipps

Eine ziemlich schöne und saubere Art, eine lesbare Fehlermeldung abzubrechen und zurückzugeben, erfolgt mit einem Signal:

Signal SQLState '45000' Set message_text = 'schueler_id und klasse_id dürfen nicht geändert werden!';

Stellen Sie sicher, dass Ihre MySQL -Version dies unterstützt, sie wurde in MySQL 5.5 vorgestellt. In früheren Versionen benötigen Sie Hacks wie das Einfügen eines nicht existierenden Feldes in eine nicht existierende Tabelle.

Wie GBN erwähnt, ist es auch eine gute Option, die neuen Werte mit den alten zu überschreiben.

Ich habe tatsächlich einen Back-Alley-Ansatz zum Abbrechen von Triggern gelernt. Es ist sehr grob, funktioniert aber, weil die Signalverarbeitung in MySQLs gespeicherter Verfahrenssprache nicht implementiert wird. Es kann bestenfalls emuliert werden.

Kapitel 11, Seiten 254-256 des Buches MySQL gespeicherte Prozedurprogrammierung unter der Unterschrift "Daten mit Triggern validieren" schlägt vor, eine Zeichenfolge in einer Dummy -Ganzzahl auszuwählen (in Bezug auf die Syntax ist sie richtig, stirbt jedoch an der Ausführung [kein Wortspiel beabsichtigt]):

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; 

Es ist tatsächlich möglich, dies ordentlich zu tun, ohne Trigger zu verwenden, wenn Sie InnoDB verwenden.

Erstellen Sie eine andere Tabelle mit nur einer Spalte. Diese Spalte sollte einen Fremdschlüssel (daher die InnoDB -Anforderung in dieser Lösung) haben, die auf die unveränderliche Spalte der fraglichen ursprünglichen Tabelle hinweist.

Setzen Sie eine Einschränkung wie "On Update Bestrict" ein.

Zusammenfassend:

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;

Basierend auf einer Kombination aller Antworten, die ich gelesen habe, hat dies für mich funktioniert:

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange
scroll top