IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PostgreSQL Discussion :

function & trigger


Sujet :

PostgreSQL

  1. #1
    Futur Membre du Club
    Inscrit en
    Novembre 2007
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 3
    Par défaut function & trigger
    Probleme qui m'a tout l'air très simple ...

    Une table de "links" et besoin de déclencher une fonction quand on met à jour la table "links".
    Deux étapes : 1) faire la fonction , 2) la déclencher.

    Je butte sur le 1) puis je buterai sur le 2) !

    CREATE TABLE links (
    linkname character varying(13) NOT NULL,
    node_a character varying(6),
    node_b character varying(6)
    );
    ALTER TABLE ONLY links
    ADD CONSTRAINT pk_links PRIMARY KEY (linkname);

    CREATE FUNCTION build_linkname( node_a varchar, node_b varchar, OUT linkname varchar) AS $$
    BEGIN
    CASE WHEN node_a < node_b
    THEN linkname = node_a ||'-'|| node_b
    ELSE linkname = node_b ||'-'|| node_a
    END;
    END;
    $$
    LANGUAGE 'sql' VOLATILE;

    -> ERROR: syntax error at or near "CASE" at character 101

    Là, je ne vois pas , je rame ....

    Un petit coup de main pour écrire le TRIGGER lors d'un INSERT ou UPDATE ... sera bienvenu aussi !

    D'avance merci,
    Bigre !

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Août 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 128
    Par défaut
    Commençons déjà par corriger la fonction. À ma connaissance, dans une fonction SQL, il n'est pas possible d'utiliser les noms des variables de la fonction. Il faut utiliser les paramètres de position : $1, $2, $3, etc. D'autre part, et ça c'est certain, une fonction SQL permet d'exécuter une ou plusieurs instructions SQL. CAST n'en est pas une. Il faut donc ajouter un SELECT devant le CAST. Enfin, dernier point : CAST ne permet pas d'affecter une valeur à une variable. En fait, CAST permet directement de renvoyer une valeur. On obtient du coup ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    CREATE FUNCTION build_linkname( node_a varchar, node_b varchar, OUT linkname varchar) AS $$
    BEGIN
    SELECT CASE WHEN $1 < $2
    THEN $1 ||'-'|| $2
    ELSE $2 ||'-'|| $1
    END;
    END;
    $$
    LANGUAGE 'sql' VOLATILE;
    Pour plus d'infos sur les fonctions SQL, voir http://www.postgresql.org/docs/8.2/i...xfunc-sql.html .

    Ça, c'est pour corriger l'erreur de syntaxe. Maintenant, je ne pense pas que cela fasse ce que tu veux. Je pense que tu veux plutôt une fonction trigger qui va modifier le contenu de la colonne linkname suivant la valeur de node_a et node_b. Premier point : une fonction trigger ne peut pas être écrite en langage SQL. Pratiquement tous les autres langages (de PL/pgsql à PL/ruby) le permettent, mais pas SQL. Donc tu vas devoir ajouter le PL/pgsql au minimum (c'est le plus simple et celui disponible par défaut). Pour ça, tu as toutes les infos sur http://www.postgresql.org/docs/8.2/i...e/plpgsql.html. Pour des infos plus spécifiques à PL/pgsql avec des triggers, tu as cette section : http://www.postgresql.org/docs/8.2/i...l-trigger.html .

  3. #3
    Futur Membre du Club
    Inscrit en
    Novembre 2007
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 3
    Par défaut
    Merci pour cette réponse ... je continue à creuser ... le plpgsql, pour une fonction aussi simple ne pose pas de problème.

    J'aurais bien vu SELECT $3, CASE .... histoire de savoir où se place le résultat de l'instruction CASE ... mais bon, je vais continuer à lire la doc et à chercher.

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Août 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 128
    Par défaut
    Le résultat du SELECT est renvoyé immédiatement par la fonction. Une fonction SQL ne fait que renvoyer le résultat de la dernière requête de la fonction.

  5. #5
    Futur Membre du Club
    Inscrit en
    Novembre 2007
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 3
    Par défaut Presque résolu
    Première étape :
    CREATE LANGUAGE plpgsql;

    La fonction qui compile ...

    CREATE OR REPLACE FUNCTION buildlinkname() returns TRIGGER AS '
    BEGIN
    IF new.linkname IS NULL
    THEN
    IF new.node_a < new.node_b
    THEN new.linkname := new.node_a ||`-`||new.node_b;
    ELSE new.linkname := new.node_b ||`-`||new.node_a;
    END IF;
    END IF;
    RETURN new;
    END;
    ' LANGUAGE plpgsql;

    linkname étant Primary Key, le premier test est superflu ... je vais l'enlever.

    Reste le trigger à mettre au point, pour ne l'exécuter que sur l'enregistremenT en cours d'insertion.

    CREATE TRIGGER trigger_linkname BEFORE INSERT ON links FOR each row execute procedure buildlinkname();

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Can't update table 'article' in stored function/trigger
    Par gentel_man dans le forum SQL Procédural
    Réponses: 4
    Dernier message: 20/03/2012, 13h51
  2. Trigger et function perso ?
    Par brolon dans le forum PL/SQL
    Réponses: 2
    Dernier message: 04/02/2009, 14h58
  3. Réponses: 0
    Dernier message: 24/06/2008, 23h51
  4. TRIGGER FUNCTION
    Par nisambou dans le forum PostgreSQL
    Réponses: 4
    Dernier message: 28/07/2004, 21h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo