Dans le corps de la gâchette, comment puis-je affecter une valeur à NEW
par son nom de champ?
[.____] C'est ce que je veux faire:
some_key = "some_column";
NEW[some_key] = 5;
Tout d'abord, là est Pas de "corps de déclenchement" (contrairement à Oracle). Dans Postgres, vous avez une fonction de déclenchement (également, trompeuse, appelée "procédure") avec un corps de fonction et des déclencheurs 0-N (sans corps) appelant cette fonction.
La variable spéciale NEW
dans la fonction de déclenchement PLPGSQL n'est ni une carte ni un tableau; c'est un record Tenir la nouvelle ligne :
NEW
Type de données
RECORD
; Variable tenant la nouvelle ligne de base de données pourINSERT
/UPDATE
Opérations dans les déclencheurs de niveau de ligne. Cette variable n'est pas affirmée dans les déclencheurs de niveau de la déclaration et pour les opérationsDELETE
.
L'attribution à un champ (ou à une colonne) de NEW
est simple. Le documenté Opérateur d'affectation est :=
. (- Depuis Postgres 9.4 =
est également documenté. )
NEW.some_key := 5;
Ce que vous semble rechercher, c'est paramétrer le nom de la colonne, qui n'est pas aussi simple.
Le Module supplémentaire hstore
fournit le #=
opérateur . (Il est inclus dans toutes les distributions standard.) Installez le module une fois par base de données avec:
CREATE EXTENSION hstore;
Ensuite vous pouvez:
NEW := NEW #= '"some_key"=>"5"'::hstore;
Définit la colonne some_key
à '5' - si la colonne existe.
hstore
est facultatif. L'opérateur #=
contrainte automatiquement un littéral de chaîne au type de données de droite.hstore
_ stocke uniquement les chaînes de texte, donc un littéral donné pour la valeur peut avoir à être coulé deux fois - Un inconvénient très mineur par rapport aux solutions alternatives.Réponse associée avec Détails et solution alternative:
CREATE OR REPLACE FUNCTION trg_tbl_ins_bef()
RETURNS trigger AS
$func$
BEGIN
NEW := NEW #= '"some_key"=>"5"';
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
CREATE TRIGGER ins_bef
BEFORE INSERT ON tbl
FOR EACH ROW EXECUTE PROCEDURE trg_tbl_ins_bef();
À Postgres 11 ou plus tard, je suggère la nouvelle syntaxe:
...
FOR EACH ROW EXECUTE FUNCTION trg_tbl_ins_bef();
Je dois admettre que ce n'est pas un moyen facile de la résoudre, mais au moins c'est un moyen. J'ai créé l'exemple ci-dessous comme une personne autonome, pour éviter tout encombrement avec la création de la gâchette et tel. Si vous l'utilisez dans un déclencheur, vous pouvez supprimer la déclaration et l'initialisation de p
et de remplacer l'utilisation restante avec NEW
.
DO $$
DECLARE p members_test;
BEGIN
p := (1,2,3);
CREATE TEMP TABLE t ON COMMIT DROP AS SELECT p.*; -- a one row table holding
-- the values of the variable
EXECUTE format($e$UPDATE t SET %s = 43$e$, 'b'); -- this way you can access
-- the columns dynamically
SELECT * INTO p FROM t; -- assign the new values back to the variable
RAISE INFO 'p: %', p;
END;
$$;
INFO: p: (1,43,3)