Vous n'êtes pas identifié(e).
J'imagine que la table metadonnees a une clef primaire avec sources_donnees, libel_colonne ? Est-ce que sources_donnees est un nom de table ?
Si c'est bien ca, il faut faire une jointure adresse --> metadonnees .
Dans un trigger , le nom de la table est dans TG_TABLE_NAME .
Pour savoir quels sont les champs modifiés, il faut comparer OLD et NEW;
Exemple :
IF (NEW.num_voie != OLD.num_voie) THEN
UPDATE metadonnees SET date_maj = now() WHERE (sources_donnees=TG_TABLE_NAME AND libel_colonne='num_voie')
END IF;
... idem pour tous les champs...
RETURN NEW
Courage ! PostgreSQL est un super outil, on peut tout faire. Essayez de bien structurer vos questions, on a parfois du mal a vous comprendre.
Alex
Bonjour,
je ne suis pas certain d'avoir bien compris ce que vous voulez faire . Avez-vous 2 tables bas_adresse... et base_adresse... ou est-ce une faute de frappe ?
En tout cas, pour mettre la date de derniere mise à jour il faut utiliser le signe d'affectation := et non pas le comparateur = .
Pour l'update, si vous ne mettez pas de clause where toute la table sera mise à jour. NEW.now() ne veut rien dire, utilisez simplement now(), il ne change pas pendant la durée de la transaction.
Un exemple simple qui marche :
CREATE FUNCTION stamp_update() RETURNS trigger
LANGUAGE plpgsql
AS $$DECLARE
nom_base varchar;
BEGIN
SELECT INTO nom_base current_database();
NEW.dat_tran := current_timestamp;
NEW.user_db_tran := nom_base;
RETURN NEW;
END;$$;
CREATE TRIGGER stamp_update BEFORE INSERT ON adresse FOR EACH ROW EXECUTE PROCEDURE stamp_update();
Je ne sais pas à quoi correspond votre table de métadonnées, mais dans un projet précédent j'avais une table d'archivage par table "utilisateur" de toutes les opérations effectuées alimentée automatiquement de cette façon (exemple tables adresse et adresse_log):
CREATE FUNCTION log_adresse() RETURNS trigger
LANGUAGE plpgsql
AS $$BEGIN
IF (TG_OP = 'DELETE' ) THEN
INSERT INTO adresse_log SELECT 'D', now(), OLD.*;
RETURN OLD;
ELSEIF (TG_OP = 'UPDATE' ) THEN
INSERT INTO adresse_log SELECT 'U', now(), NEW.*;
RETURN NEW;
ELSEIF (TG_OP = 'INSERT' ) THEN
INSERT INTO adresse_log SELECT 'I', now(), NEW.*;
RETURN NEW;
END IF;
RETURN NULL; END;$$;
CREATE TRIGGER xlog_adresse BEFORE INSERT OR DELETE OR UPDATE ON adresse FOR EACH ROW EXECUTE PROCEDURE log_adresse();
Les 2 tables ont la meme structure , a part un champ code transaction et un timestamp en plus pour la table log.
J'espère que ces exemples vous aideront.
Alex
Bonjour,
il y a 3 ans j’ai utilisé avec succès apgdiff : Another PostGreSQL Diff Tool .
Il permet de comparer 2 exports et générer un script pour rendre la structure des 2 bases identiques.
Je ne sais pas s’il est toujours d’actualité, mais ça vaut sûrement la peine d’y jeter un oeil.
Alex Leguevaques
Cette discussion vous aidera aussi certainement.
Alex
Bonjour, vous pouvez aller voir cette discussion pour démarrer.
Alex
Oups ! Il s'agit de modifier le fichier postgresql.conf !
Désolé pour le bruit.
Alex
Dans pg_hba.conf , mettre
listen_addresses = '*'
pour accepter toutes les connections ou
listen_addresses='localhost,192.168.0.1'
par exemple pour les connections locales + l'adresse Ip 192.168.0.1 .
Alex
En ce qui concerne les requêtes récursives, Pg les connait depuis au moins la 8.4 .
Voir dans ce forum ce thread et la documentation sur le create view ou la documentation sur les CTE .
Bonjour,
le "problème de lenteur" est une idée reçue datant de Pg 7.4 (qui date de 2003 !) .
Il est vrai que MySQL a été conçu en privilégiant les performances plutôt que la fiabilité, alors que Pg a fait le choix inverse.
Mais depuis plusieurs années, d'énormes progrès ont été faits des 2 côtés pour gommer les défauts.
L'évolution de Pg me semble plus rapide et allant dans le bon sens, de plus on peut discuter du fait que MySQL soit vraiment open source,
puisque c'est la propriété d'Oracle, alors que Pg est développé par la communauté .
Pg semble être en plein décollage, avec des fonctionnalités innovantes à chaque release, tous les ans depuis 3 ou 4 ans, voir cet article.
Une recherche sur Google vous permettra de trouver des comparatifs qui vous éclaireront.
Pour ce qui est du développement Web , lisez le témoignage de Christophe Legendre, DBA de "leboncoin.fr".
Alex
Le mail dans mon profil était obsolète, je l'ai corrigé.
Bonne continuation
Alex
La déclaration de curseur ne sert à rien . Pour Java, je suis totalement incompétent sur le sujet. Essayez dans Forum PostgreSQL.fr et Java .
Si vous voulez faire des triggers plus compliqués, je peux vous donner des tonnes d'exemples, de quelques dizaines à quelques centaines de lignes.
Plutôt par MP, pour ne pas surcharger inutilement le forum.
Alex
Je me suis mal fait comprendre.
Soit une table "matable" avec un champ id de type integer et un champ alp de type varchar(10).
Si vous avez un trigger "before update" de la table "matable" qui appelle la fonction "mon-calcul", l'enchaînement est le suivant :
1) Un client (appli, psql...) exécute
UPDATE matable set alp = "a" WHERE id = 1;
2) PostgreSQL déclenche le trigger qui active la fonction mon-calcul.
Cette fonction prend la main juste avant que l'update soit réalisé.
Admettons que la fonction mon-calcul contienne une ligne :
IF (NEW.alp = "a") THEN
NEW.alp := "x"
END IF;
3) Cette ligne est suffisante pour que la ligne soit stockée avec les valeurs 1 et "x" .
Il ne faut surtout pas faire d'update de matable dans la fonction, car le trigger sera déclenché qui activera la fonction avec l'update qui...etc...
Pour résumer, dans une fonction trigger before update, vous êtes en train de faire l'update, et vous pouvez intervenir "au vol" pour faire les contrôles que vous voulez. Dans votre fonction trigger, il ne devrait y avoir que :
-- Function: calc_surfaceutile()
-- DROP FUNCTION calc_surfaceutile();
CREATE OR REPLACE FUNCTION calc_surfaceutile()
RETURNS trigger AS
$BODY$BEGIN
BEGIN
IF (NEW.art_vch_surface IS NOT NULL) THEN
NEW.art_dec_surfaceutile := (NEW.art_dec_coefchutearticlepopup * NEW.art_vch_surface);
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION calc_surfaceutile()
OWNER TO postgres;
Le trigger devrait ressembler à ça :
DROP TRIGGER calc_surfaceutile ON article;
CREATE TRIGGER calc_surfaceutile
BEFORE INSERT OR UPDATE
ON article
FOR EACH ROW
EXECUTE PROCEDURE calc_surfaceutile();
Lorsque ce sera en place, tous les insert et update mettront à jour la colonne art_dec_surfaceutile de la table article.
Il y a la mise à jour des lignes existantes à faire, soit au préalable (avant de créer le trigger), soit en ayant désactivé le trigger le temps de l'update , soit en faisant une fausse modif pour déclencher le trigger sur toutes les lignes.
J'utilise phpPgAdmin et psql et ne connais pas PgAdmin, je ne peux rien dire là dessus.
Pour le reste, lorsqu'une fonction est appelée dans un trigger, certaines variables sont créées et valorisées automatiquement par PostgresSQL :
NEW : contient la ligne qui va être enregistrée (valable en UPDATE ou INSERT uniquement). On accède aux champs avec NEW.champ1, NEW.champ2...etc... Si on modifie un champ et que le trigger se termine bien, cette nouvelle valeur sera stockée.
OLD : la ligne avant les modifs (valable en UPDATE ou DELETE uniquement)
Pour plus d'infos voir Triggers procedures .
La fonction peut être appelée d'autres triggers, on peut même faire une fonction "générique" qui teste le cas INSERT/UPDATE/DELETE et effectue des traitements spécifiques.
Exemple :
IF (TG_OP = 'INSERT') THEN
NEW.dat_creat := current_timestamp;
NEW.user_db_creat := current_user;
ELSEIF (TG_OP = 'UPDATE') THEN
NEW.dat_tran := current_timestamp;
NEW.user_db_tran := current_user;
END IF;
Je ne parle que des triggers au niveau ligne, en 9.3 il y a les "event triggers" qui se déclenchent lors des ordres DDL (CREATE TABLE, DROP TABLE...)
mais vous verrez ça plus tard...
En relisant votre message, je crois comprendre la confusion que vous faites.
Un trigger (= déclencheur en français) est un évènement que vous pouvez intercepter pour mettre du code .
Exemple ci-dessus pour renseigner base d'origine et date / heure création à chaque insert.
Si, comme je crois avoir compris, vous ajoutez un champ calculé dans votre table, il vous faut faire 2 choses :
1) Un update pour l'existant, par exemple :
UPDATE matable set colonneresultat_dematable = colonne1_dematable * colonne2_dematable
WHERE colonne2_dematable IS NOT NULL;
2) Une fonction appelée dans un trigger "before insert or update" qui fera simplement :
CREATE FUNCTION majtot() RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
IF (colonne2_dematable IS NOT NULL) THEN
NEW.colonneresultat_dematable := NEW.colonne1_dematable * New.colonne2_de ma table;
END IF;
RETURN NEW;
END;
$$;
ALTER FUNCTION public.majtot() OWNER TO toto;
Notez le ":=" pour l'affectation et le ";" en fin de ligne .
La création du trigger :
CREATE TRIGGER trg_majtot
BEFORE INSERT OR UPDATE ON matable
FOR EACH ROW
EXECUTE PROCEDURE majtot();
Avec ça, toutes les modifs et créations calculeront le nouveau champ.
Bonjour,
voici un exemple de fonction appelée dans un trigger :
CREATE FUNCTION stamp_insert() RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
nom_base varchar;
BEGIN
SELECT INTO nom_base current_database();
NEW.dat_creat := current_timestamp;
NEW.user_db_creat := nom_base;
RETURN NEW;
END;
$$;
ALTER FUNCTION public.stamp_insert() OWNER TO toto;
et le trigger :
CREATE TRIGGER stamp_insert
BEFORE INSERT ON matable
FOR EACH ROW
EXECUTE PROCEDURE stamp_insert();
Espérant vous aider
Alex
Bonjour,
pour le dernier message, il faut aller dans Préférences systèmes ==> Sécurité et confidentialité et débloquer PgAdmin (pour OS X 10.9) ou
autoriser les applications téléchargées de n'importe où (< 10.9) , installer PgAdmin , et remettre "Mac App Store et développeurs identifiés" (je vous le conseille, la sécurité est à ce prix) .
Alex
Bonjour,
vous pouvez utiliser un CASE :
SELECT a,
CASE WHEN a IS TRUE THEN 'TRUE'
WHEN a IS FALSE THEN 'FALSE'
ELSE 'UNKNOWN'
END
FROM toto;
Alex
Je crois que vous n'avez pas créé l'extension pgcrypto, comme indiqué par rjuju . Exemple :
$ psql
psql (9.2.4)
Saisissez « help » pour l'aide.
conclavi_test=# select encrypt('azerty','fooz','bf');
ERREUR: la fonction encrypt(unknown, unknown, unknown) n'existe pas
LIGNE 1 : select encrypt('azerty','fooz','bf');
^
ASTUCE : Aucune fonction ne correspond au nom donné et aux types d'arguments.
Vous devez ajouter des conversions explicites de type.
conclavi_test=# \dx
Liste des extensions installées
Nom | Version | Schéma | Description
---------+---------+------------+------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(1 ligne)
conclavi_test=# create extension pgcrypto;
CREATE EXTENSION
conclavi_test=# \dx
Liste des extensions installées
Nom | Version | Schéma | Description
----------+---------+------------+------------------------------
pgcrypto | 1.0 | public | cryptographic functions
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(2 lignes)
conclavi_test=# select encrypt('azerty','fooz','bf');
encrypt
--------------------
\x888475ea29dbb241
(1 ligne)
conclavi_test=#
Alex
Bonjour,
un exemple :
$sql = "insert into licencie(id_licencie,id_identite,qualif_cartet,diplome,discipline)
values(default,$identiter,'$carte_pro','$diplome','$discipline')returning id_licencie";
$result = pg_query($db, $sql);
if (!$result) {
die("Erreur SQL: " . pg_last_error());
}
$ligne = pg_fetch_row($result);
$id_licencie = $ligne[0];
Alex
Bonjour,
j'ai l'impression que les quotes autour de mot_de_passe sont en trop :
select id, decrypt(mot_de_passe,'1234','aes') from utilisateur where ...
L'exemple donné dans la doc parle de : encrypt(data, 'fooz', 'bf')
Alex
Bonjour,
Si vous voulez réinitialiser une séquence , la doc est là : Fonctions de manipulation de séquences .
Sinon, pourriez-vous préciser votre question ?
Alex
Pg 9.4 risque d'avoir quelques arguments supplémentaires pour séduire les clients Oracle
Bonjour,
j'ai lu avec le plus grand intérêt l'article AXLE improves analytics on Big Data .
Bien que n'étant pas directement concerné, cette future extension des possibilités de PostgreSQL ne peut que nous conforter dans notre choix.
Néanmoins, je me pose quelques questions sur l'interprétation de :
First deliverables from the project will be submitted to PostgreSQL version 9.4, available in 2014 and will continue in later releases.
Est-ce que AXLE sera une extension, comme PostGIS ? Ou PostgreSQL sera-t-il modifié en profondeur ? Et dans ce cas, il faudra un dialogue entre AXLE et la core team de PostgreSQL ?
Quid des arbitrages ? Simple curiosité de ma part .
Alex
Bonjour,
j'utilise pour ma part apgdiff : http://www.apgdiff.com/
Alex