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 Re : Général » Alternative de commit, rollback dans une procédure stockée » 10/07/2015 14:36:36

En fait, le problème c'est que l'exécution de la fonction va certainement prendre du temps (une journée et même plus). Donc au moins s'il y a commit, les données validées seront enregistrées dans la base.
Ci-après la fonction - qu'en pensez-vous ? La table appartement contient 104000 enregistrements ...
J'aimerais ajouter commit avant end loop mais ce n'est pas possible? comment faire ou comment optimiser cette fonction?

===============================
CREATE OR REPLACE FUNCTION generer_avis_imposition(var_exer_annee character varying, dat_avis_impos_date_limite date, int_operateur integer)
  RETURNS character varying AS
$BODY$DECLARE
    -- Declaration
BEGIN
    var_role_type  := 'IF';
   
    SELECT INTO enreg *
    FROM role
    WHERE exer_annee= var_exer_annee
    AND role_type = var_role_type
    AND role_homolo IS NULL;
   
    IF enreg.role_code IS NULL THEN
        --avis_impos_ref
        SELECT valeur_param_exer_val INTO int_role_num
        FROM valeur_param_exercice
        WHERE param_exer_key = 'SEQ_ROLE_IF' ;
       
        INSERT INTO role (exer_annee, role_type,role_num,role_article) VALUES (var_exer_annee, var_role_type,int_role_num,1)
        --recupere code apres insert
        RETURNING "role_code" INTO STRICT int_rode_code; 
       
        --mise à jour sequence
        UPDATE valeur_param_exercice
        SET valeur_param_exer_val = int_role_num + 1
        WHERE param_exer_key = 'SEQ_ROLE_IF' ;
    ELSE
        int_rode_code = enreg.role_code ;
    END IF;
   
    SELECT param_valeur INTO var_avis_impos_verificateur
    FROM param_sys
    WHERE param_key = 'P_NOM_VERIFICATEUR' ;

    FOR enreg IN (SELECT
                a.bien_code,
                parcel_adresse , appart_superf_batie , parcel_superf_non_batie ,pr.dec_decoup_terri_code as rue  ,quartier
                FROM
                appartement AS a
                INNER JOIN batiment AS ba ON ba.batim_code = a.batim_code
                INNER JOIN parcelle as pr ON pr.bien_code = ba.bien_code
                INNER JOIN proprietaire_bien AS p ON p.bien_code = a.bien_code
                INNER JOIN (SELECT A.type_decoup_code as type , A.decoup_terri_code as quartier , B.decoup_terri_code
                            FROM decoupage_territoire as A
                            INNER JOIN decoupage_territoire as B on A.decoup_terri_code = B.dec_decoup_terri_code
                            ) AS dec ON dec.decoup_terri_code = pr.dec_decoup_terri_code
                WHERE (a.appart_declare_if = 'f' OR a.appart_declare_if IS NULL)
                AND appart_superf_batie > 0)
                LOOP       
                                                                   
                SELECT INTO enreg_2 c.contri_nif , c.contri_adresse
                FROM proprietaire_bien as p
                INNER JOIN contribuable as c ON c.contri_nif = p.contri_nif
                WHERE p.bien_code = enreg.bien_code;

                t_avis_impos_adresse_contribuable := enreg_2.contri_adresse ;
                v_contri_nif := enreg_2.contri_nif ;                       

                --avis_impos_ref
                SELECT valeur_param_exer_val INTO int_valeur_param_exer_val
                FROM valeur_param_exercice
                WHERE param_exer_key = 'SEQ_AI' ;
               
                --liste contribuable
                t_avis_impos_contribuable := '' ;
                v_sep := '';
                FOR enreg_2 IN (SELECT *
                                FROM vw_contribuable
                                WHERE bien_code = enreg.bien_code ) LOOP
                   
                    t_avis_impos_contribuable :=  t_avis_impos_contribuable || v_sep || enreg_2.contri_nom_rs ;
                    v_sep := ',';
                END LOOP;
               
                v_avis_impos_ref = int_valeur_param_exer_val || '/' ||var_exer_annee ;
               
                t_avis_impos_adresse_bien     := enreg.parcel_adresse ;
                t_avis_impos_quartier         := enreg.quartier ;
               
                -- numéro article
                SELECT MAX(avis_impos_article::int) INTO int_max_avis_impos_article
                FROM avis_imposition
                WHERE role_code = int_rode_code ;
               
                IF int_max_avis_impos_article IS NULL THEN
                    int_avis_impos_article := 1 ;
                ELSE
                    int_avis_impos_article := int_max_avis_impos_article + 1 ;
                END IF;
               
                INSERT INTO avis_imposition (contri_nif,exer_annee,role_code ,avis_impos_ref , avis_impos_contribuable,avis_impos_adresse_bien , avis_impos_quartier ,avis_impos_bien ,avis_impos_adresse_contribuable , avis_impos_article ,avis_impos_date_limite ,avis_impos_verificateur ,operateur , avis_impos_genere)
                VALUES (v_contri_nif,var_exer_annee, int_rode_code , v_avis_impos_ref , t_avis_impos_contribuable , t_avis_impos_adresse_bien ,t_avis_impos_quartier , enreg.bien_code ,t_avis_impos_adresse_contribuable,int_avis_impos_article,dat_avis_impos_date_limite , var_avis_impos_verificateur , int_operateur ,'t')
                RETURNING "avis_impos_code" INTO STRICT int_avis_impos_code;
               
                --mise à jour sequence
                UPDATE valeur_param_exercice
                SET valeur_param_exer_val = int_valeur_param_exer_val + 1
                WHERE param_exer_key = 'SEQ_AI' ;
                ---Article role
               
                ---detail   
                res := regenerer_details_avis_if(int_avis_impos_code, enreg.bien_code , var_exer_annee , NULL ) ;
               
                SELECT
                    SUM( COALESCE( det_avis_if_taux_batie , 0) * COALESCE(det_avis_if_surf_batie,0) )
                    + SUM(COALESCE(det_avis_if_taux_non_batie,0) * COALESCE(det_avis_if_surf_non_batie ,0) ) INTO flo_avis_impos_mt_ppal
                FROM details_avis_if
                WHERE avis_impos_code =  int_avis_impos_code ;
               
                UPDATE avis_imposition
                SET avis_impos_mt_ppal = flo_avis_impos_mt_ppal ,
                avis_impos_reste_ppal = flo_avis_impos_mt_ppal
                WHERE avis_impos_code = int_avis_impos_code ;

                UPDATE appartement
                SET appart_declare_if = 't'
                WHERE bien_code = enreg.bien_code ;
               
                -- COMMIT;
    END LOOP;-- end appartement
   
    --mise à jour article role
    UPDATE role SET role_article = (SELECT MAX(avis_impos_article::int) FROM avis_imposition WHERE role_code = int_rode_code)  WHERE role_code = int_rode_code ;
   
    RETURN '1' ;
END;$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION regenere_avis_imposition(character varying, date, integer)
  OWNER TO postgres;
========================================

Merci.
Serge

#2 Général » Alternative de commit, rollback dans une procédure stockée » 10/07/2015 14:01:44

srr2015
Réponses : 3

Bonjour,

J'ai créé une fonction (procédure stockée) qui nécessite l'insertion dans une table avec plusieurs millliers d'enregistrements.
J'aimerais donc faire un commit par lot de 10000 enregistrements par exemple. Comme l'utilisation de commit et rollback n'est permise dans une fonction, existe-il une alternative pour que l'insertion soit effective après traitement de 10000 enregistrements?
Toutes suggestions sont les bienvenues.

Merci d'avance.

Pied de page des forums

Propulsé par FluxBB