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

  1. #1
    Modérateur

    Avatar de MaitrePylos
    Homme Profil pro
    DBA & Dev PHP
    Inscrit en
    juin 2005
    Messages
    5 005
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : DBA & Dev PHP
    Secteur : Service public

    Informations forums :
    Inscription : juin 2005
    Messages : 5 005
    Points : 11 159
    Points
    11 159

    Par défaut Function utilisation Perform

    Bonjour,
    J'ai créé la fonction suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    CREATE FUNCTION brain.update_hash_people ()
    	RETURNS bool
    	LANGUAGE plpgsql
    	VOLATILE 
    	CALLED ON NULL INPUT
    	SECURITY INVOKER
    	COST 1
    	AS $$
    DECLARE
    v_id_people int;
    v_hash varchar;
    BEGIN
        -- génère les hash
        FOR v_id_people,v_hash
        IN select id_people,hash from brain.update_hash
        LOOP
            select id_people from brain.people where id_people = v_id_people and hash = v_hash;
            if not found THEN
            update brain.people set hash = v_hash, modification = false;
            end if;
        END LOOP;
    return true;
    END;
    $$;

    du coup j'ai l'erreur suivante :

    SQL Error [42601]: ERROR: query has no destination for result data
    Indice*: If you want to discard the results of a SELECT, use PERFORM instead.
    Où*: PL/pgSQL function update_hash_people() line 10 at SQL statement
    Je modifie donc 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
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    CREATE FUNCTION brain.update_hash_people ()
    	RETURNS bool
    	LANGUAGE plpgsql
    	VOLATILE 
    	CALLED ON NULL INPUT
    	SECURITY INVOKER
    	COST 1
    	AS $$
    DECLARE
    v_id_people int;
    v_hash varchar;
    BEGIN
        -- génère les hash
        FOR v_id_people,v_hash
        IN select id_people,hash from brain.update_hash
        LOOP
            perform id_people from brain.people where id_people = v_id_people and hash = v_hash;
            if not found THEN
            update brain.people set hash = v_hash, modification = false;
            end if;
        END LOOP;
    return true;
    END;
    $$;

    Et là cela tourne en boucle, j’arrête après plusieurs minutes.
    Pouvez-vous m'orienter vers une solution ?

    Merci

  2. #2
    Modérateur

    Homme Profil pro
    Consultant Teradata
    Inscrit en
    septembre 2008
    Messages
    7 844
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Consultant Teradata

    Informations forums :
    Inscription : septembre 2008
    Messages : 7 844
    Points : 15 562
    Points
    15 562

    Par défaut

    Pour perform je ne sais pas, mais j'ai quelques remarques sur la fonction.

    Côté non réponse, je suppose que ça vient du manque de where id_people = v_id_people dans l'update (ligne #20-21) - du coup toute la table est mise à jour à chaque ligne du select, c'est long et ça génère beaucoup de contention.

    Ensuite la logique me paraît erronée, j'aurai écrit une simple commande comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     merge into brain.people as tgt
     using brain.update_hash as src
        on tgt.id_people    = src.id_people
      when matched then update
       set tgt.hash         = src.hash
         , tgt.modification = false
     where tgt.hash        <> src.hash
        or tgt.hash        is null;
    Syntaxe à vérifier, je ne suis pas sûr du niveau d'implémentation de la commande MERGE chez PostgreSQL.

  3. #3
    Modérateur

    Avatar de MaitrePylos
    Homme Profil pro
    DBA & Dev PHP
    Inscrit en
    juin 2005
    Messages
    5 005
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : DBA & Dev PHP
    Secteur : Service public

    Informations forums :
    Inscription : juin 2005
    Messages : 5 005
    Points : 11 159
    Points
    11 159

    Par défaut

    Merge n'existe pas chez PostgreSQL, en tout cas pas l'implémentation standard de SQL, il faut utiliser upsert.
    Par contre oui, j'ai vu ce matin que j'avais oublié le where.
    En fait, le souci, venais...de je ne sais où, il à juste fallut réorganiser le façon de faire, je ne pense pas que cela soit la meilleur solution, mais je fais ceci qui fonctionne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    CREATE FUNCTION brain.update_hash_people ()
    	RETURNS bool
    	LANGUAGE plpgsql
    	VOLATILE 
    	CALLED ON NULL INPUT
    	SECURITY INVOKER
    	COST 1
    	AS $$
    DECLARE
    v_id_people int;
    v_hash varchar;
    v_compteur integer;
    BEGIN
        -- génère les hash
        FOR v_id_people,v_hash
        IN select id_people,hash from brain.update_hash
        LOOP
            select count(id_people) into v_compteur from brain.people where id_people = v_id_people and hash = v_hash;
            if v_compteur = 0 THEN
            update brain.people set hash = v_hash, modification = false where id_people = v_id_people;
            end if;
        END LOOP;
    return true;
    END;
    $$;
    En gros j'ajoute une variable (v_compteur) dans le process et c'est lui qui va me servir de discriminant.
    Je pense que PostgreSQL ne sait pas me dire si je retourne quelque chose ou pas...je m'y prend surement mal.

    Maintenant , je vais me pencher sur ta solution.

    merci.

  4. #4
    Modérateur

    Homme Profil pro
    Consultant Teradata
    Inscrit en
    septembre 2008
    Messages
    7 844
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Consultant Teradata

    Informations forums :
    Inscription : septembre 2008
    Messages : 7 844
    Points : 15 562
    Points
    15 562

    Par défaut

    Peut-être comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    update brain.people      as tgt
       set tgt.hash         = src.hash
         , tgt.modification = false
      from brain.update_hash as src
     where tgt.id_people    = src.id_people
       and (tgt.hash       <> src.hash
        or  tgt.hash       is null);

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

Discussions similaires

  1. s-function utilisation aide
    Par benza dans le forum Simulink
    Réponses: 1
    Dernier message: 17/09/2012, 08h28
  2. Problème function utilisant mysql
    Par guismojames dans le forum Fonctions
    Réponses: 2
    Dernier message: 12/02/2010, 01h16
  3. Function utilisable dans plusieurs classes
    Par zulot dans le forum C++
    Réponses: 7
    Dernier message: 05/06/2007, 00h01
  4. performances des virtual functions
    Par xxiemeciel dans le forum C++
    Réponses: 2
    Dernier message: 25/07/2005, 17h24
  5. [FLASH MX2004] Utilisation de function
    Par mohican13 dans le forum Flash
    Réponses: 2
    Dernier message: 25/02/2005, 14h33

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