web-dev-qa-db-fra.com

Fonction de déclenchement postgresql avec paramètres

Je veux créer un déclencheur sur une table appelée prend dans postgresql pour mettre à jour une valeur dans une autre table appelée student J'essaie de le faire de la manière suivante. Mais je reçois une erreur indiquant qu'il y a une erreur de syntaxe près de "OLD". Je ne comprends pas ce qui ne va pas avec ça. Voici mon code:

CREATE OR REPLACE FUNCTION upd8_cred_func
      (id1 VARCHAR, gr1 VARCHAR,id2 VARCHAR, gr2 VARCHAR) 
      RETURNS void AS $$
 BEGIN
    IF  (id1=id2 and gr1 is null and gr2 is not null) THEN 
        update student set tot_cred = tot_cred + 6 where id = id1;
    END IF;
    RETURN;
 END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER upd8_cred
    AFTER UPDATE ON takes
    FOR EACH ROW
    EXECUTE PROCEDURE upd8_cred_func(OLD.id,OLD.grade,NEW.id,NEW.grade);
29
user975474

Vous n'avez pas besoin de passer les paramètres NEW et OLD en tant que paramètres à la fonction de déclenchement. Ils sont automagiquement disponibles ici:

http://www.postgresql.org/docs/9.1/interactive/trigger-definition.html :

La fonction déclencheur doit être déclarée comme une fonction ne prenant aucun argument et renvoyant un déclencheur de type. (La fonction de déclenchement reçoit son entrée via une structure TriggerData spécialement passée, pas sous la forme d'arguments de fonction ordinaires.)

À propos des enregistrements passés à la procédure de déclenchement, veuillez consulter http://www.postgresql.org/docs/9.1/interactive/plpgsql-trigger.html :

Lorsqu'une fonction PL/pgSQL est appelée comme déclencheur, plusieurs variables spéciales sont créées automatiquement dans le bloc de niveau supérieur. Ils sont: [...] NOUVEAUX, [...] ANCIENS [...]

Comme SeldomNeedy l'a souligné dans le commentaire ci-dessous, vous pouvez toujours passer et utiliser des paramètres à la fonction de déclenchement. Vous déclarez la fonction comme ne prenant aucun paramètre, mais quand définissant le déclencheur (par CREATE TRIGGER), vous pouvez en ajouter.

Ils seront disponibles pour le déclencheur sous la forme TG_NARG (le nombre de ces paramètres) et TG_ARGV[] (un tableau de texte valeurs).

29
Arsen7

Comme Greg l'a déclaré, les fonctions de déclenchement peuvent prendre des arguments, mais les fonctions elles-mêmes ne peuvent pas avoir de paramètres déclarés. Voici un exemple simple dans plpgsql:

CREATE TABLE my_table ( ID SERIAL PRIMARY KEY ); -- onelined for compactness

CREATE OR REPLACE FUNCTION raise_a_notice() RETURNS TRIGGER AS
$$
DECLARE
    arg TEXT;
BEGIN
    FOREACH arg IN ARRAY TG_ARGV LOOP
        RAISE NOTICE 'Why would you pass in ''%''?',arg;
    END LOOP;
    RETURN NEW; -- in plpgsql you must return OLD, NEW, or another record of table's type
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER no_inserts_without_notices BEFORE INSERT ON my_table
FOR EACH ROW EXECUTE PROCEDURE raise_a_notice('spoiled fish','stunned parrots');

INSERT INTO my_table DEFAULT VALUES;

-- the above kicks out the following:
--
-- NOTICE:  Why would you pass in 'spoiled fish'?
-- NOTICE:  Why would you pass in 'stunned parrots'?
--

Il y a quelques autres goodies tels que TG_NARGS (pour savoir combien d'arguments vous avez obtenus sans les parcourir) discuté dans la documentation . Il y a également des informations sur la façon d'obtenir le nom de la table de déclenchement au cas où vous auriez une logique principalement mais pas assez partagée pour une fonction de déclenchement qui s'étend sur un certain nombre de tables.

15
SeldomNeedy

La fonction de déclenchement peut avoir des paramètres, mais vous ne pouvez pas faire passer ces paramètres comme une fonction normale (par exemple, des arguments dans la définition de la fonction). Vous pouvez obtenir le même résultat ... En python vous avez accès aux données ANCIENNES et NOUVELLES comme le décrit la réponse ci-dessus. Par exemple, je peux utiliser TD ['new'] ['column_name '] dans python pour référencer les nouvelles données pour nom_colonne. Vous avez également accès à la variable spéciale TD [' args ']. Donc, si vous le souhaitez:

create function te() returns trigger language plpython2u as $function$
    plpy.log("argument passed 1:%s 2:%s" %(TD['args'][0], TD['args'][1], ))
$function$

create constraint trigger ta after update of ttable
for each for execute procedure te('myarg1','myarg2');

Certes, ces arguments sont statiques, mais ils sont utiles lors de l'appel d'une fonction de déclencheur commune à partir de plusieurs déclarations de déclencheur. Je suis à peu près sûr que les mêmes variables sont disponibles pour d'autres langages de procédures stockées. (désolé si le code ne fonctionne pas textuellement, mais je pratique cette technique, donc je sais que vous pouvez passer des arguments!).

13
Greg