web-dev-qa-db-fra.com

Comment créer un déclencheur Postgres pour s'assurer que le champ est non mis à jour

J'essaie de créer un déclencheur Postgres pour vous assurer que la valeur d'une colonne a été définie, elle ne peut pas être mise à jour (essentiellement le rendre réadien). Jusqu'à présent, j'ai proposé le projet de déclencheur suivant.

1) D'abord, suis-je sur la bonne piste?
[.____] 2) Y a-t-il une valeur dans le retour NEW?
3) Dois-je préférer original_id avec NEW.?

CREATE FUNCTION check_id_change() RETURNS TRIGGER AS $$
    BEGIN
        IF OLD.original_id <> NEW.original_id THEN
            RAISE EXCEPTION 'cannot change original_id'; 
        END IF;
        RETURN NEW;
    END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER client_update_trigger AFTER UPDATE ON client FOR EACH ROW
      EXECUTE PROCEDURE check_id_change();
5
user1322092

Utiliser un before update gâchette.

Voulez-vous soulever une exception ou simplement le faire en silence de ne pas changer la valeur?

Oui, vous devriez revenir NEW.

Oui, vous devez préfixer le nom de la colonne avec NEW ou OLD.

Vous pouvez l'utiliser si vous ne voulez pas constituer une exception:

create function check_id_change() returns trigger language plpgsql as $$
begin

  new.original_id = old.original_id;

  return new;

end $$;
4
Neil McGuigan

Créer un BEFORE UPDATE sur votre colonne spécifique original_id.
Notez que l'application utilisant la DB doit être consciente de ses contraintes, il est donc préférable de soulever une exception lorsque la colonne est mise à jour, afin d'informer la couche d'application d'une défaillance, au lieu de simplement ignorer la mise à jour.

CREATE OR REPLACE FUNCTION check_id_change()
  RETURNS TRIGGER AS
$BODY$
BEGIN
  IF NEW."original_id" IS DISTINCT FROM OLD."original_id"
  THEN
    RAISE EXCEPTION '"original_id" column cannot get updated';
  END IF;

  RETURN NEW;
END;
$BODY$ LANGUAGE PLPGSQL;

CREATE TRIGGER client_update_trigger
BEFORE UPDATE OF "original_id"
  ON "client"
FOR EACH ROW
EXECUTE PROCEDURE check_id_change();

Ou en utilisant WHEN condition

CREATE OR REPLACE FUNCTION check_id_change()
  RETURNS TRIGGER AS
$BODY$
BEGIN
  RAISE EXCEPTION '"original_id" column cannot get updated';
END;
$BODY$ LANGUAGE PLPGSQL;

CREATE TRIGGER client_update_trigger
BEFORE UPDATE OF "original_id"
  ON "client"
FOR EACH ROW
WHEN (NEW."original_id" IS DISTINCT FROM OLD."original_id")
EXECUTE PROCEDURE check_id_change();

NOTE UTILISATION IS DISTINCT FROM comparaison au lieu de <> ou alors != Sauf si la colonne ait NOT NULL ou vous êtes sûr que la valeur ne sera jamais la valeur NULL.

8
mahdavipanah