Vous n'êtes pas identifié(e).
Pages : 1
Bonjour,
Nous utilisons des triggers sur notre base de données, afin d'alimenter une table "synchronisation" permettant de synchroniser les données d'une base cliente à partir d'une base serveur. Seule une partie des tables de la base sont synchronisées. La liste des tables synchronisées est définie dans une table de la base : "synchro_entite".
Parmis les tables synchronisées, il y en a 3 qui sont liées à une GED, et qui permettent de récupérer des images ou documents, liés à d'autres tables de la BDD. Ces 3 tables sont :
- "document" : qui contient le nom du document, et le type du document
- "doclien" : qui fait la relation entre un document et une entité de la base (le nom de la table + son id)
- "docversion" : qui contient des infos sur le document (date, utilisateur, taille,...) et le OID lié au document
Lors de l'ajout d'un document, on insère bien des données dans les 3 tables successivement. Mais il est possible qu'une insertion se passe mal, et que seule la table "document" soit mise à jour.
De même, on sait si le document est à synchronisé que lorsqu'on mets à jour "doclien", car c'est lui qui sait à quelle table est liée un document.
Le trigger actuellement utilisé est le suivant :
-- Function: fct_add_document_to_synchro()
-- DROP FUNCTION fct_add_document_to_synchro();
CREATE OR REPLACE FUNCTION fct_add_document_to_synchro()
RETURNS trigger AS
$BODY$
DECLARE
curtime timestamp;
ptrs_id bigint;
type_op text;
table_name text;
i_count integer;
i_synchro integer;
BEGIN
type_op := TG_OP;
IF type_op LIKE 'DELETE' THEN
return OLD;
END IF;
curtime := 'now';
ptrs_id := NEW.id;
table_name := TG_TABLE_NAME;
i_synchro := 1;
-- si table 'document' et opération 'update'
IF table_name = 'document' AND type_op LIKE 'UPDATE' THEN
-- i_synchro = nb d'occurences dans 'doclien' liés au document_id (ptrs_id) et
SELECT INTO i_synchro COUNT(1) FROM doclien dl
WHERE document_id = ptrs_id
AND UPPER(dl.entite) IN (
SELECT UPPER(nomtable) FROM synchro_entite WHERE actif = true
);
-- si table 'doclien'
ELSIF table_name = 'doclien' THEN
SELECT INTO i_synchro COUNT(1) FROM synchro_entite s_e
WHERE UPPER(s_e.nomtable) = UPPER(NEW.entite)
AND s_e.actif = true;
-- si table 'docversion'
ELSIF table_name = 'docversion' THEN
SELECT INTO i_synchro COUNT(1) FROM doclien dl
WHERE document_id = NEW.document_id
AND UPPER(dl.entite) IN (
SELECT UPPER(nomtable) FROM synchro_entite WHERE actif = true
);
-- sinon
ELSE
i_synchro = 0;
END IF;
IF i_synchro > 0 THEN
-- Verifie s'il n'existe pas déja un enregistrement dans la base
SELECT INTO i_count COUNT(nom_table) FROM synchronisation
WHERE id_ptrs = ptrs_id AND nom_table = table_name ;
IF i_count <= 0 THEN
INSERT INTO synchronisation (id_ptrs, nom_table, etat, date_maj_ptrs)
VALUES (ptrs_id, table_name, type_op, curtime);
ELSE
UPDATE synchronisation
SET etat = type_op, date_maj_ptrs = curtime
WHERE id_ptrs = ptrs_id AND nom_table = table_name;
END IF;
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
ALTER FUNCTION fct_add_document_to_synchro() OWNER TO postgres;
GRANT EXECUTE ON FUNCTION fct_add_document_to_synchro() TO public;
GRANT EXECUTE ON FUNCTION fct_add_document_to_synchro() TO postgres;
COMMENT ON FUNCTION fct_add_document_to_synchro() IS 'Fonction d''ajout d''enregistrements de documents dans la table ''synchronisation'' (serveur/PTRS)';
Il ne me convient pas, car il ne marche que pour un UPDATE. Il faudrait que je l'adapte pour qu'il marche aussi dans le cas ou on ajoute un document. Mais comme le document est ajouté avant doclien, je ne sais pas trop quelle solution utiliser :
- faire un update de "document" après avoir inséré un "doclien" dans ma méthode de sauvegarde, pour que le trigger soit appelé?
- ajouter systématiquement tous les documents ajoutés via le trigger, et créer un trigger qui va "faire le ménage" après avoir ajouté un "doclien"?
Hors ligne
De même, on sait si le document est à synchronisé que lorsqu'on mets à jour "doclien", car c'est lui qui sait à quelle table est liée un document.
donc le trigger est actuellement posé sur la table doclien ?
Il ne me convient pas, car il ne marche que pour un UPDATE. Il faudrait que je l'adapte pour qu'il marche aussi dans le cas ou on ajoute un document. Mais comme le document est ajouté avant doclien, je ne sais pas trop quelle solution utiliser :
je suis désolé mais ce que vous décrivez m'apparaît confus (ca vient probablement de moi ;-)).
Pouvez vous préciser à partir de quel(s) succession d'événement(s) une synchronisation doit elle être planifiée ?
Dès l'insertion/modification de documents ou seulement après que doclien ait été mis à jour ?
Ou une autre succession de mises à jour, peu importe mais merci de la définir précisément ?
Si il s'agit "simplement" de synchroniser chaque table indépendamment de ce qui se passe dans les autres je suppose qu'une solution envisageable
est de poser la même fonction triggers sur toutes les tables qui se contenterait d'enregistrer dans la table synchronisation les modifications
effectuées.
Par contre si la synchronisation ne doit intervenir que sous certaines conditions qui concernent de multiples tables la solution sera différente.
Éric
Hors ligne
C'est vrai que j'ai oublié de préciser que nous avions un déclencheur pour chacune de ces 3 tables. Par exemple, pour la table "document", le trigger est :
-- Trigger: TRG_AFTER_DOCUMENT on "document"
-- DROP TRIGGER "TRG_AFTER_DOCUMENT" ON "document";
CREATE TRIGGER "TRG_AFTER_DOCUMENT"
AFTER INSERT OR UPDATE OR DELETE
ON "document"
FOR EACH ROW
EXECUTE PROCEDURE fct_add_document_to_synchro();
Et c'est donc ce déclencheur qui appelle la fonction trigger que j'ai présenté dans mon premier message : "fct_add_document_to_synchro".
La synchronisation sera planifiée chaque jour pour mettre à jour les données du client à partir de nos données.
Les triggers servent donc à alimenter la table "synchronisation" qui sera utilisée lors de la synchronisation.
Hors ligne
Moi, ce qui m'échappe, c'est ce paragraphe:
«Lors de l'ajout d'un document, on insère bien des données dans les 3 tables successivement. Mais il est possible qu'une insertion se passe mal, et que seule la table "document" soit mise à jour.» Pourquoi ne pas utiliser une transaction ? C'est à ça qu'elles servent, et ça vous simplifierait le problème non ?
Marc.
Hors ligne
Moi, ce qui m'échappe, c'est ce paragraphe:
«Lors de l'ajout d'un document, on insère bien des données dans les 3 tables successivement. Mais il est possible qu'une insertion se passe mal, et que seule la table "document" soit mise à jour.» Pourquoi ne pas utiliser une transaction ? C'est à ça qu'elles servent, et ça vous simplifierait le problème non ?
Ca résuoudrait certainement le problème oui.
Mais le prestataire qui avait développé pour nous la solution n'a utilisé nulle part de transactions, de clés étrangères, ou de bonnes pratiques qu'on devrait sans doute retrouver avec une base PostgreSQL...
Du coup, l'idée est surtout de finaliser le module de synchronisation des données le plus simplement possible, sans revenir sur la "pseudo" couche d'accès aux données existantes pour le reste de la solution.
Hors ligne
Sinon, pour répondre à la question initiale, je pense que la première solution (update) est plus propre et plus sûre que la seconde (ménage).
Marc.
Hors ligne
D'accord merci.
Hors ligne
Pages : 1