Question

Je veux faire une colonne dans une relation unmodifyable pour des raisons de cohérence.

La trame de fond est que je suis un n: n relation où la relation « liaison » a des valeurs supplémentaires. Je ne veux pas que tout le monde est capable de modifier les ID des partenaires relationnels.

Ce que je suis venu avec à ce jour:

Création d'un élément déclencheur qui vérifie si la nouvelle valeur est la même que l'ancienne valeur. Mais je ne sais pas comment nier l'action UPDATE si la condition se révèle comme vrai.

Voici mon déclencheur jusqu'à présent:

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;
Était-ce utile?

La solution

Au lieu de faire avorter la mise à jour, juste écraser?

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

Autres conseils

Une assez belle et propre façon pour annuler et renvoyer un message d'erreur est lisible en utilisant un signal:

SIGNAL SQLSTATE '45000' SET texte_message = 'Schueler_ID et Klasse_ID ne peuvent pas être modifiés!

Assurez-vous que votre Do version MySQL prend en charge, il a été introduit dans MySQL 5.5. Dans les versions précédentes, vous devez hacks comme l'insertion d'un champ non existant dans une table non existant.

Comme gbn mentionne, les nouvelles valeurs en écrasant les anciennes est une bonne option aussi.

En fait, j'appris une approche de ruelle de déclencheurs abandon. Il est très brut, mais fonctionne parce que le traitement du signal est pas implémentée dans la procédure stockée Langue de MySQL. Il peut être émulé au mieux.

Chapitre 11, pages 254-256 du livre MySQL procédure stockée programmation sous la rubrique Validation des données avec triggers ' suggère de faire un SELECT d'une chaîne de caractères dans un nombre entier factice (en termes de syntaxe, il est correct, mais meurt sur l'exécution [NO pun intended]):

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; 

Il est en fait possible de le faire d'une manière ordonnée sans utiliser les déclencheurs si vous utilisez InnoDB.

Créer une autre table avec une seule colonne. Cette colonne doit avoir une clé étrangère (d'où l'exigence InnoDB dans cette solution) qui pointe vers la colonne immuable de la table d'origine en question.

Mettre une restriction comme "ON UPDATE restrict".

En résumé:

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;

Sur la base d'une combinaison de toutes les réponses que j'ai lu c'est ce qui a fonctionné pour moi:

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top