PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 02/12/2013 12:23:18

Eleanis
Membre

Fonction dynamique/mise à jour sur la même table.

Bonjour à tous,

je créé actuellement une fonction dans une base pgsql sous phpPgAdmin.

Je dois récupéré les enregistrements d'une table "p_nom_table" ou la ligne du numéro de déclaration vaut "no_decla_s", jusque là tout va bien, c'est quand je dois UPDATE cette même table "p_nom_table" à la ligne ou le numero de declaration vaut 0, une sorte de ligne de saisie, que cela se corse.

En fait j'utilise des requête dynamiques et je bloque lors de l'insertion dans la meme table car le pgsql n'accepte pas le SELECT INTO dans un EXECUTE si j'ai bien compris. J'ai eut beau tout essayer en passant par des alias, stocker la sous-requête dans un RECORD, des SELECT INTO USING....rien ne marche.
Le problème se trouve à la fin de la fonction au niveau des EXECUTE.

Alors si vous avez une idée pour corriger mon code je suis preneur car là je sèche vraiment...en espérant avoir expliqué assez clairement mon problème.

D'avance merci pour votre aide.

Ci-dessous le code de ma fonction:

DECLARE
    p_nom_table VARCHAR;       
    p_column_nodecl VARCHAR;   
    p_column_typedecl VARCHAR;
    p_column VARCHAR;
    p_where_s VARCHAR;
    p_count NUMERIC;
        rec RECORD;
    no_declar_s NUMERIC;
    all_columns_s VARCHAR;
    all_columns_d VARCHAR;

BEGIN
 
 
  -- Boucle permetttant d'etablir la liste des tables a copier pour le type de declaration passes en parametre.

    FOR p_nom_table IN
        SELECT NOM_TABLE
        FROM SPA_TABLE_CLASSE
        WHERE TYPE_DECLAR = P_TYPE_DECLAR
    LOOP
--        RAISE NOTICE 'Traitement de la table %',p_nom_table;
        SELECT column_name INTO p_column_nodecl FROM information_schema.columns
            WHERE table_name= LOWER(p_nom_table) AND column_name LIKE 'no_declar%';
        SELECT column_name INTO p_column_typedecl FROM information_schema.columns
            WHERE table_name= LOWER(p_nom_table) AND column_name LIKE 'type_declar%';

--         RAISE NOTICE 'Recuperation du n° de declaration active dans la table source %',p_nom_table;
        SELECT no_declar INTO no_declar_s FROM SPA_DECLAR
            WHERE TYPE_DECLAR = P_TYPE_DECLAR AND etat = 'A';
                       
--        RAISE NOTICE 'Traitement de la table % (% et %)',p_nom_table,p_column_nodecl,p_column_typedecl;
        if p_column_typedecl is null then
            p_where_s = p_column_nodecl || ' = ' || no_declar_s;
        else
            p_where_s = p_column_nodecl || ' = ' || no_declar_s || ' AND ' || p_column_typedecl || ' = ''' || P_TYPE_DECLAR || '''';

        end if;

--        Ici, il faut lister toutes les colonnes de la table
--        Elles serviront pour le insert FROM select dans lequel on positionnera le nouveau no_declar
        all_columns_s := '';
        all_columns_d := '';
        FOR p_column IN
            SELECT column_name
            FROM information_schema.columns
            WHERE table_name= LOWER(p_nom_table)
        LOOP
            if all_columns_s != '' and p_column != p_column_nodecl
            then
                all_columns_s := all_columns_s || ',';
            end if;
            if all_columns_d != '' and p_column != p_column_nodecl
            then
                all_columns_d := all_columns_d || ',';
            end if;
           
            if p_column != p_column_nodecl
            then
                all_columns_d := all_columns_d || p_column;
                all_columns_s := all_columns_s || p_column;
            end if;
        END LOOP;
       

        EXECUTE 'SELECT '||all_columns_s||' FROM $2 WHERE $3 = $4 INTO rec USING '||p_nom_table||','||p_column_nodecl||','||no_declar_s||'';
    EXECUTE 'UPDATE '||p_nom_table||' SET ('||all_columns_d||') = '||rec||' WHERE '||p_column_nodecl||' = 0';
       
        --RAISE NOTICE '%',sql_query;
        EXECUTE sql_query;
    END LOOP;
END;



MAJ: J'ai essayé aussi par une vue temporaire et la seconde requete (UPDATE) plante toujours...
EXECUTE 'CREATE TEMPORARY VIEW REC AS SELECT '||all_columns_s||' FROM '||p_nom_table||' WHERE '||p_column_nodecl||' = '||no_declar_s||'';

EXECUTE 'UPDATE '||p_nom_table||' SET ('||all_columns_d||') = (SELECT * from REC) WHERE '||p_column_nodecl||' = 0';

Dernière modification par Eleanis (02/12/2013 15:59:26)

Hors ligne

#2 03/12/2013 10:56:48

Eleanis
Membre

Re : Fonction dynamique/mise à jour sur la même table.

Problème résolu, j'ai inséré le préfixe "s." devant toutes les colonnes source

all_columns_s := all_columns_s || 's.'||p_column;

puis la requête suivante est passée:

EXECUTE 'UPDATE '||p_nom_table||' SET ('||all_columns_d||') = ('||all_columns_s||')
                FROM (SELECT '||all_columns_d||' FROM '||p_nom_table||' WHERE '||p_where_s||') s
                WHERE '||p_column_nodecl||' = 0';

Merci quand meme a ceux qui ont pris le temps de regarder mon immonde pavé wink!

Hors ligne

Pied de page des forums