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 :

Nom de table calculé dans trigger


Sujet :

PostgreSQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Février 2006
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 21
    Par défaut Nom de table calculé dans trigger
    Bonjour à tous,

    j'ai un probleme de création de trigger : en quelques mots, voici ce que je voudrais faire :

    Enregistrer des logs dans des tables séparées dont le nom serait logs_YYYYMM
    par exemple logs_200909, logs_2009_10...

    Pour celà actuellement on a créé un trigger comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    DECLARE
        mois varchar;
    BEGIN
        mois = to_char(to_timestamp(NEW.timestamp/1000), 'MM');
        ELSIF (mois ='09') THEN
            INSERT INTO logs_200909 VALUES (NEW.*);
        ELSIF (mois ='10') THEN
            INSERT INTO logs_200910 VALUES (NEW.*);    
        ELSE
            RAISE EXCEPTION 'Mois non prevu';
        END IF;
        RETURN NULL;
    END;
    Mais tant qu'à faire, autant créer quelque chose de plus générique, du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        mois = to_char(to_timestamp(NEW.timestamp/1000), 'YYYYMM');
        INSERT INTO logs_????? VALUES (NEW.*);

    Comment faire s'il vous plait pour calculer, concaténer ce nom de table dans le trigger ?

    merci d'avance

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Par défaut
    Il faut construire la requête SQL INSERT dans une chaine de caractères, et la passer en argument à EXECUTE (on appelle ça du SQL dynamique ou généré):
    http://www.postgresql.org/docs/8.3/s...-EXECUTING-DYN

  3. #3
    Membre à l'essai
    Inscrit en
    Septembre 2009
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Septembre 2009
    Messages : 7
    Par défaut
    Bonjour,

    As tu essayé quelque chose du genre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Execute 'insert into logs_'||to_char(now(),'YYYMM')|| ' values ....'

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Février 2006
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 21
    Par défaut
    merci pour vos réponses.

    ça marche... presque

    j'ai testé pas mal de choses avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CREATE OR REPLACE FUNCTION logs_insert_trigger()
      RETURNS trigger AS
    $BODY$
    DECLARE
        mois varchar;
    BEGIN
        mois = to_char(to_timestamp(NEW.timestamp/1000), 'YYYYMM');
        Execute 'insert into logs_'||mois||' values ('||NEW.message||','||NEW.timestamp||','||NEW.mail||','||NEW.category||','||NEW.priority ||');';
        RETURN NULL;
    END;
    MAIS

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     ERROR:  syntax error at or near "reussie" at character 50
     QUERY:  insert into logs_200909 values (Authentification reussie par [xxxx@xxx] de l'entité [ddd@eee] sur l'application [fxr],1254210602300,ddd@eee,log.auth,INFO);
    CONTEXT:  PL/pgSQL function "logs_insert_trigger" line 5 at EXECUTE statement
    STATEMENT:  INSERT INTO LOGS (message,timestamp,mail,category,priority) VALUES($1,$2,$3,$4,$5)
    ERROR:  syntax error at or near "d" at character 45
    QUERY:  insert into logs_200909 values (Acquisition d'un profil sur l'application [fxr] par [ddd@eee] de l'entité ddd@eee],1254210602369,ddd@eee,log.auth,INFO);
    CONTEXT:  PL/pgSQL function "logs_insert_trigger" line 5 at EXECUTE statement
    2009-09-29 09:53:13 CEST STATEMENT:  INSERT INTO LOGS (message,timestamp,mail,category,priority) VALUES($1,$2,$3,$4,$5)
    note :j'ai caché les adresses mail

    On a essayé d'échapper les caractères, en vain. Peut etre y a t'il un autre moyen ?

    Quand on le fait, on a
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    identifier "acquisition_dun_profil_sur_lapplication__xxxe__par__patrick_xxx" 
    will be truncated to 
    "acquisition_dun_profil_sur_lapplication__xxxe__par__patrick_"
    suivi d'un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    column "acquisition_dun_profil_sur_lapplication__xxxe__par__patrick_" 
    does not exist at character 81
    merci pour votre aide si vous avez d'autres idées

  5. #5
    Membre à l'essai
    Inscrit en
    Septembre 2009
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Septembre 2009
    Messages : 7
    Par défaut
    Oui c'est le probleme quand on ecrit du SQL dynamique.

    Il faut remplacer certains caracteres comme ' par deux quotes ''
    en gros pour despecialiser une quote faut mettre deux quotes

    replace(NEW.message,'''','''''')

    Apres autres probleme que vous rencontrez, il faut que les valeurs de votre insert soit entre quote (au moins pour tout ce qui est de type text)

    il faut passer de ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    INSERT INTO logs_200909 VALUES (Acquisition d'un profil sur l'application [fxr] par [ddd@eee] de l'entité ddd@eee],1254210602369,ddd@eee,log.auth,INFO);
    à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    INSERT INTO logs_200909 VALUES ('Acquisition d''un profil sur l''application [fxr] par [ddd@eee] de l''entité [e mail]ddd@eee] ','1254210602369','ddd@eee','log.auth[/email]','INFO');
    ca qui doit donner quelque chose dans ce genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Execute 'insert into logs_'||mois||' values ('''||replace(NEW.message,'''','''''')||''','''||NEW.timestamp||''','''||NEW.mail||''','''||NEW.category||''','''||NEW.priority ||''');';
    Deuxieme verification à faire, je vois que dans votre insert vous ne precisez pas les colonnes, donc il faut quelles soient toutes renseignées et dans le bon ordre dans la clause value.

    Sinon precisez le nom des colonnes

    par exemple une table comportant 6 colonnes, et je n'insert que des valeurs dans 3 colonnes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into table1 (col1,col2,col6) values (val1,val2,val6);
    si je ne precise pas les colonnes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into table1 values (val1,val2,val3,val4,val5,val6);
    Bon courage

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Par défaut
    Suggestion: utiliser la fonction quote_literal qui s'occupe de mettre les apostrophes qui vont bien au début, à la fin, et à l'intérieur si nécessaire, et qui de plus devrait aussi gérer le problème d'un éventuel backslash dans le contenu, tout en donnant un code plus lisible.
    Exemple de la doc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    EXECUTE 'UPDATE tbl SET '
            || quote_ident(colname)
            || ' = '
            || quote_literal(newvalue)
            || ' WHERE key = '
            || quote_literal(keyvalue);

  7. #7
    Membre à l'essai
    Inscrit en
    Septembre 2009
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Septembre 2009
    Messages : 7
    Par défaut
    Merci pour cette suggestion Estofilo, bien pratique cette fonction.

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

Discussions similaires

  1. [MySQL] Nom de table dynamique dans une jointure
    Par CsJoe dans le forum PHP & Base de données
    Réponses: 9
    Dernier message: 05/08/2009, 14h13
  2. Requète SQL avec nom de table contenu dans une variable
    Par samoussa dans le forum Langage SQL
    Réponses: 2
    Dernier message: 13/05/2009, 13h58
  3. [MS SQL SERVER 2k5]nom de table dynamique dans un curseur
    Par patriceharel dans le forum Développement
    Réponses: 2
    Dernier message: 16/12/2008, 11h03
  4. Nom de la table courante dans trigger
    Par lenoil dans le forum PL/SQL
    Réponses: 3
    Dernier message: 09/01/2008, 09h01
  5. Réponses: 2
    Dernier message: 06/04/2007, 11h48

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