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 » un dernier trigger pour la route » 26/01/2012 13:00:30

ioguix > c'est peut etre stressant d'etre étudiant à 20 ans, mais passé 40 ça l'est encore plus et digérer un programme universitaire de 2 ans en 6 mois ne simplifie pas la tache, surtout quand on part du zéro absolue. à l'issue de ma formation je ne compte pas faire une carrière de DBA mais plutôt m'orienter vers le développement en Java. J'ai juste besoin de finir ce trigger pour boucler mon projet qui a déjà 2 jours de retard, suite à quoi je ne toucherais surement plus aux bases de données, du moins pas à un niveau aussi complexe. Cela explique mon agacement car je suis plutôt du genre à préférer un petit dessin qu'un long discours.

Marc > merci pour vos explications, notamment concernant le phénomène de boucle, j'avais déjà eu ce cas de figure 1 fois, mais là j'étais complètement passé à coté. concernant les NEW et le non-sens de les modifier, je n'ai malheureusement toujours pas compris la mécanique...
Maintenant le temps me manque, je dois rendre le projet dans 1h, je vais donc le rendre incomplet et serrer les fesses pour avoir une note suffisante qui rattrapera la sale note que j'ai eu sous Oracle

-----------------------

Merci à tous ceux qui ont passé du temps à m'aider, je regrette de ne pas être arrivé au bout malgré vos efforts et les miens

#2 Re : Général » un dernier trigger pour la route » 26/01/2012 11:46:14

que de condescendance, facile d'enfoncer les gens quand on sait faire et que les autres ne l'ont jamais fait...

si je repose la meme question c'est justement pcq je n'ai pas compris, c'est d'exemples que j'ai besoin !
je suis allé voir les exemples de la doc (lien ci-dessus) mais je ne comprend tjrs pas comment les données s'insèrent dans la table, ya pas d'update/insert dans une table.

les lignes suivantes :
NEW.datemodif := current_date;
NEW.auteurmodif := current_user;
servent-elles juste à donner des valeurs AVANT de faire la requête update sur ma table ?

#3 Re : Général » un dernier trigger pour la route » 26/01/2012 11:00:19

flo > merci, super intervention

si quelqu'un te dit qu'il n'a pas compris et que tu lui répetes exactement la meme chose, penses-tu réellement que ça le fera avancer de lui redire la meme chose ? ne penses tu pas qu'une reformulation serait plus judicieux ?

#4 Re : Général » un dernier trigger pour la route » 26/01/2012 10:32:17

voila la version d'hier soir

CREATE OR REPLACE FUNCTION fonction_autobackup() RETURNS TRIGGER AS $$
DECLARE
ok1 boolean;
ok2 boolean;
protec integer;
nbrbackup integer;

BEGIN
-- verifie si le current_user est l'auteur de ce sujet
SELECT (current_user = auteur) INTO ok1 FROM  ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
-- verifie si le current_user est autorisé à modifier ce sujet
SELECT (current_user = autorisedtomodif) INTO ok2 FROM AUTORIS WHERE NUMSUJET = NEW.NUMSUJET;
--- vérifie si la PROTECTION est désactivée (valeur à 0)
SELECT protection into protec FROM ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
IF protec=0 THEN ok1="true";
END IF;

IF ok1 or ok2 THEN
	-- archivage du sujet modifié
	INSERT INTO LGPBAK 
		(NUMBACKUP,NUMSUJET,AUTEUR,TITRE,DATEMODIF,AUTEURMODIF,TEXTE)
		SELECT OLD.NUMBACKUP, OLD.NUMSUJET, OLD.AUTEUR,OLD.TITRE, OLD.DATEMODIF, 
		OLD.AUTEURMODIF, OLD.TEXTE
		FROM ALLSUJET
		WHERE NUMSUJET=NEW.NUMSUJET;
	-- test sur le nombre de sauvegarde du sujet
	-- si >10 on supprime le 11ème pour n'en garder que 10
	SELECT COUNT(numbackup) INTO nbrbackup from lgpbak WHERE old.numsujet=new.numsujet GROUP BY numsujet;
		IF nbrbackup>10 THEN
			DELETE FROM lgpbak WHERE numbackup=(SELECT MIN(numbackup) 
			FROM lgpbak where numsujet = old.numsujet) 
			AND old.numsujet=new.numsujet;
		END IF;
	-- update du sujet 
	-- avec date de modif + update de AUTEURMODIF + incrémentation du compteur NUMBACKUP
	UPDATE ALLSUJET SET 
		titre = NEW.titre ,
		NEW.datemodif = current_date;
		NEW.auteurmodif = current_user;
		OLD.numbackup = numbackup+1,
		texte = NEW.texte
		WHERE NUMSUJET = NEW.NUMSUJET;
		RETURN NEW;

	ELSE
	RAISE WARNING 'L''utilisateur % n''est pas autorise à modifier le sujet numero %', current_user, NEW.numsujet;
	RETURN NULL;
	END IF;
END;
$$ LANGUAGE plpgsql;

Gleu > en lisant ton dernier message  je me dis que je n'ai apparemment pas bien compris ce qu'il fallait faire... sauf que je ne sais pas quoi faire d'autre que ce que j'ai déjà fait sad

#5 Re : Général » un dernier trigger pour la route » 26/01/2012 01:14:41

rien a faire, le trigger ne veut pas s'enregistrer avec la syntaxe ":="
postgres ne semble accepter que les "=" sans les ":"

d'autre part la requete se met toujours en erreur :

CREATE OR REPLACE FUNCTION fonction_autobackup() RETURNS TRIGGER AS $$
DECLARE
ok1 boolean;
ok2 boolean;
protec integer;
nbrbackup integer;

BEGIN
-- verifie si le current_user est l'auteur de ce sujet
SELECT (current_user = auteur) INTO ok1 FROM  ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
-- verifie si le current_user est autorisé à modifier ce sujet
SELECT (current_user = autorisedtomodif) INTO ok2 FROM AUTORIS WHERE NUMSUJET = NEW.NUMSUJET;
--- vérifie si la PROTECTION est désactivée (valeur à 0)
SELECT protection into protec FROM ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
IF protec=0 THEN ok1="true";
END IF;

IF ok1 or ok2 THEN
	-- archivage du sujet modifié
	INSERT INTO LGPBAK 
		(NUMBACKUP,NUMSUJET,AUTEUR,TITRE,DATEMODIF,AUTEURMODIF,TEXTE)
		SELECT OLD.NUMBACKUP, OLD.NUMSUJET, OLD.AUTEUR,OLD.TITRE, OLD.DATEMODIF, 
		OLD.AUTEURMODIF, OLD.TEXTE
		FROM ALLSUJET
		WHERE NUMSUJET=NEW.NUMSUJET;
	-- test sur le nombre de sauvegarde du sujet
	-- si >10 on supprime le 11ème pour n'en garder que 10
	SELECT COUNT(numbackup) INTO nbrbackup from lgpbak WHERE old.numsujet=new.numsujet GROUP BY numsujet;
		IF nbrbackup>10 THEN
			DELETE FROM lgpbak WHERE numbackup=(SELECT MIN(numbackup) 
			FROM lgpbak where numsujet = old.numsujet) 
			AND old.numsujet=new.numsujet;
		END IF;
	-- update du sujet 
	-- avec date de modif + update de AUTEURMODIF + incrémentation du compteur NUMBACKUP
	UPDATE ALLSUJET SET 
		titre = NEW.titre ,
		NEW.datemodif = current_date;
		NEW.auteurmodif = current_user;
		OLD.numbackup = numbackup+1,
		texte = NEW.texte
		WHERE NUMSUJET = NEW.NUMSUJET;
		RETURN NEW;

	ELSE
	RAISE WARNING 'L''utilisateur % n''est pas autorise à modifier le sujet numero %', current_user, NEW.numsujet;
	RETURN NULL;
	END IF;
END;
$$ LANGUAGE plpgsql;

voila l'erreur

UPDATE ALLSUJET SET titre = 'test UPDATE' WHERE numsujet=2;
ERREUR:  la colonne « new » de la relation « allsujet » n'existe pas
LIGNE 3 : NEW.datemodif = current_date
          ^
REQUÊTE : UPDATE ALLSUJET SET 
titre = NEW.titre ,
NEW.datemodif = current_date
CONTEXTE : PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL

il semble qu'il ne veuille pas du NEW non plus sad

#6 Re : Général » un dernier trigger pour la route » 26/01/2012 00:35:16

je n'ai jamais fait ça.... yikes

comment je procède pour récupérer les valeurs à entrer dans les NEW ?
pcq à part NEW.truc = OLD.truc je vois pas, et c'est déjà ce que j'ai précédemment fait

#7 Re : Général » un dernier trigger pour la route » 25/01/2012 23:25:42

j'ai mis un NEW partout mais j'avais une erreur pour le TITRE
de meme les ":=" provoquaient une erreur lors de l'insertion du trigger, c'est pas plutot une syntaxe Oracle ?

bref, j'ai enlevé les NEW et n'ai gardé que ceux sur la datemodif et auteurmodif, voici l'erreur que ça me retourne

 UPDATE ALLSUJET SET titre = 'test UPDATE' WHERE numsujet=2;

ERREUR:  la colonne « new » de la relation « allsujet » n'existe pas
LIGNE 3 : NEW.datemodif = current_date,
          ^
REQUÊTE : UPDATE ALLSUJET SET 
titre = NEW.titre ,
NEW.datemodif = current_date,
NEW.auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET
CONTEXTE : PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL

en tout cas merci à vous deux d'essayer de m'aider

#8 Re : Général » un dernier trigger pour la route » 25/01/2012 22:59:20

rjuju > merci pour la correction

gleu > désolé mais ça m'a échappé, le message d'erreur était long et j'avoue que ce trigger commence sérieusement à me sortir par les yeux, 2 jours que je suis dessus. d'autre part à l'issue de ma formation je ne compte pas devenir dba. néanmoins j'ai déjà foiré le devoir sur Oracle, j'ai donc besoin d'une note correcte sur ce projet (que je devais rendre déjà hier) raison pour laquelle je m'acharne à le finir.

---------------

en parlant de message d'erreur à rallonge, en voici un qui rempli la console (désolé mais j'ai pas le début) :

datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL

il semble que ce soit une erreur de boucle, mais je vois pas où ça boucle... pfff j'en ai marre

#9 Re : Général » un dernier trigger pour la route » 25/01/2012 22:27:56

bon ben je n'y arrive toujours pas... pour tester j'ai enlevé la contrainte UNIQUE et meme pas mis de PK :

CREATE TABLE LGPBAK
	(NUMBACKUP INTEGER,
	NUMSUJET INTEGER REFERENCES LGPSUJET (NUMSUJET),
	AUTEUR VARCHAR(25) REFERENCES LGPUTILS (NOM),
	TITRE VARCHAR,
	DATEMODIF DATE,
	AUTEURMODIF VARCHAR(25),
	TEXTE VARCHAR	
	);

grant select on LGPBAK to public;
grant insert on LGPBAK to public;
grant delete on LGPBAK to public;

CREATE VIEW BACKSUJET AS SELECT * FROM LGPBAK;
grant select on BACKSUJET to public;
grant insert on BACKSUJET to public;
grant delete on BACKSUJET to public;	

--------------------------------------------------

-- TRIGGER = archivage des sujets modifiés
CREATE OR REPLACE FUNCTION fonction_autobackup() RETURNS TRIGGER AS $$
DECLARE
ok1 boolean;
ok2 boolean;
protec integer;
nbrbackup integer;

BEGIN
-- verifie si le current_user est l'auteur de ce sujet
SELECT (current_user = auteur) INTO ok1 FROM  ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
-- verifie si le current_user est autorisé à modifier ce sujet
SELECT (current_user = autorisedtomodif) INTO ok2 FROM AUTORIS WHERE NUMSUJET = NEW.NUMSUJET;
--- vérifie si la PROTECTION est désactivée (valeur à 0)
SELECT protection into protec FROM ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
IF protec=0 THEN ok1="true";
END IF;

IF ok1 or ok2 THEN
	-- archivage du sujet modifié
	INSERT INTO LGPBAK 
		(NUMBACKUP,NUMSUJET,AUTEUR,TITRE,DATEMODIF,AUTEURMODIF,TEXTE)
		SELECT OLD.NUMBACKUP, OLD.NUMSUJET, OLD.AUTEUR,OLD.TITRE, OLD.DATEMODIF, 
		OLD.AUTEURMODIF, OLD.TEXTE
		FROM ALLSUJET
		WHERE NUMSUJET=NEW.NUMSUJET;
	-- test sur le nombre de sauvegarde du sujet
	-- si >10 on supprime le 11ème pour n'en garder que 10
	SELECT COUNT(numbackup) INTO nbrbackup from lgpbak WHERE old.numsujet=new.numsujet GROUP BY numsujet;
		IF nbrbackup>10 THEN
		DELETE FROM lgpbak WHERE numbackup=MIN(numbackup) AND old.numsujet=new.numsujet;
		END IF;
	-- update du sujet 
	-- avec date de modif + update de AUTEURMODIF + incrémentation du compteur NUMBACKUP
	UPDATE ALLSUJET SET 
		titre = NEW.titre ,
		datemodif = current_date,
		auteurmodif = current_user,
		numbackup = numbackup+1,
		texte = NEW.texte
		WHERE NUMSUJET = NEW.NUMSUJET;
		RETURN NEW;

	ELSE
	RAISE WARNING 'L''utilisateur % n''est pas autorise à modifier le sujet numero %', current_user, NEW.numsujet;
	RETURN NULL;
	END IF;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER fonction_autobackup 
INSTEAD OF UPDATE ON ALLSUJET
FOR EACH ROW EXECUTE PROCEDURE fonction_autobackup();
UPDATE ALLSUJET SET titre = 'test UPDATE' WHERE numsujet=2;


ERREUR:  agrégats non autorisés dans une clause WHERE
LIGNE 1 : DELETE FROM lgpbak WHERE numbackup=MIN(numbackup) AND old.nu...
                                             ^
REQUÊTE : DELETE FROM lgpbak WHERE numbackup=MIN(numbackup) AND old.numsujet=new.numsujet
CONTEXTE : PL/pgSQL function "fonction_autobackup" line 31 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET 
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL

pffff, j'ai le cerveau tout vide à force...

#10 Re : Général » un dernier trigger pour la route » 25/01/2012 22:06:33

je n'avais pas du tout pensé à ça, surtout que la table LGPBACK était vide... merci bcp pour le renseignement wink

#11 Re : Général » un dernier trigger pour la route » 25/01/2012 20:55:36

je ne m'en sort toujours pas avec ce trigger, j'y ai passé tout mon aprem et tjrs pas de résultat
help please

#12 Re : Général » un dernier trigger pour la route » 24/01/2012 23:57:16

bizarre, j'avais pourtant essayé de les supprimer et ça n'avait pas fonctionné... peut etre m'étais-je trompé de requete :s
depuis j'ai corrigé une autre erreur (auteurmodif était déclaré en integer au lieu de varchar, vestige d'une ancienne version avant que je change la PK avec le nom d'auteur plutot que son n°)

et maintenant je tombe sur un nouveau probleme :

voila la nouvelle version du trigger :

CREATE OR REPLACE FUNCTION fonction_autobackup() RETURNS TRIGGER AS $$
DECLARE
ok1 boolean;
ok2 boolean;
protec integer;
nbrbackup integer;
BEGIN
-- ****** verification de propriete du sujet ou de l'autorisation de modification *******
-- verifie si le current_user est l'auteur de ce sujet
SELECT (current_user = auteur) INTO ok1 FROM  ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
-- verifier si le current_user est autorisé à modifier ce sujet
SELECT (current_user = autorisedtomodif) INTO ok2 FROM AUTORIS WHERE NUMSUJET = NEW.NUMSUJET;
--- vérifie si la PROTECTION est désactivée (valeur à 0)
SELECT protection into protec FROM ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
IF protec=0 THEN ok1="true";
END IF;

IF ok1 or ok2 THEN
	-- archivage du sujet modifié
	INSERT INTO LGPBAK 
	(NUMBACKUP,NUMSUJET,AUTEUR,TITRE,DATEMODIF,AUTEURMODIF,TEXTE)
	SELECT OLD.NUMBACKUP, OLD.NUMSUJET, OLD.AUTEUR,OLD.TITRE, OLD.DATEMODIF, 
	OLD.AUTEURMODIF, OLD.TEXTE
	FROM ALLSUJET
	WHERE NUMSUJET=NEW.NUMSUJET;

	-- test sur le nombre de sauvegarde du sujet
	-- si >10 on supprime le 11ème pour n'en garder que 10
	SELECT COUNT(numbackup) INTO nbrbackup from lgpbak WHERE old.numsujet=new.numsujet GROUP BY numsujet;
		IF nbrbackup>10 THEN
		DELETE FROM lgpbak WHERE numbackup=MIN(numbackup) AND old.numsujet=new.numsujet;
		END IF;

	-- update du sujet 
	-- avec date de modif + update de AUTEURMODIF + incrémentation du compteur NUMBACKUP
	UPDATE ALLSUJET SET 
		titre = NEW.titre ,
		datemodif = current_date,
		auteurmodif = current_user,
		numbackup = numbackup+1,
		texte = NEW.texte
		WHERE NUMSUJET = NEW.NUMSUJET;
		RETURN NEW;

	ELSE
	RAISE WARNING 'L''utilisateur % n''est pas autorise à modifier le sujet numero %', current_user, NEW.numsujet;
	RETURN NULL;
	END IF;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER fonction_autobackup 
INSTEAD OF UPDATE ON ALLSUJET
FOR EACH ROW EXECUTE PROCEDURE fonction_autobackup();

et nouvelle erreur :

postgres=> UPDATE ALLSUJET SET titre = 'test UPDATE1' WHERE numsujet=2;

ERREUR:  la valeur d'une clé dupliquée rompt la contrainte unique « lgpbak_numbackup_key »
DÉTAIL : La clé « (numbackup)=(1) » existe déjà.
CONTEXTE : instruction SQL « INSERT INTO LGPBAK
(NUMBACKUP,NUMSUJET,AUTEUR,TITRE,DATEMODIF,AUTEURMODIF,TEXTE)
SELECT OLD.NUMBACKUP, OLD.NUMSUJET, OLD.AUTEUR,OLD.TITRE, OLD.DATEMODIF,
OLD.AUTEURMODIF, OLD.TEXTE
FROM ALLSUJET
WHERE NUMSUJET=NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 20 at instruction SQL
instruction SQL « UPDATE ALLSUJET SET
titre = NEW.titre ,
datemodif = current_date,
auteurmodif = current_user ,
numbackup = numbackup+1,
texte = NEW.texte
WHERE NUMSUJET = NEW.NUMSUJET »
PL/pgSQL function "fonction_autobackup" line 36 at instruction SQL


pourtant j'incrémente de 1 la valeur de NUMBACKUP lors de l'update dans la table des sujets, et la table des backup est vide....

#13 Re : Général » un dernier trigger pour la route » 24/01/2012 23:16:24

houlala, je suis fatigué moi, à force de retourner le prb dans tout les sens je deviens aveugle...

maintenant j'ai un nouveau probleme de syntaxe :

CREATE OR REPLACE FUNCTION fonction_autobackup() RETURNS TRIGGER AS $$
DECLARE
ok1 boolean;
ok2 boolean;
protec integer;
nbrbackup integer;
BEGIN
-- ****** verification de propriete du sujet ou de l'autorisation de modification *******
-- verifie si le current_user est l'auteur de ce sujet
SELECT (current_user = auteur) INTO ok1 FROM  ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
-- verifier si le current_user est autorisé à modifier ce sujet
SELECT (current_user = autorisedtomodif) INTO ok2 FROM AUTORIS WHERE NUMSUJET = NEW.NUMSUJET;
--- vérifie si la PROTECTION est désactivée (valeur à 0)
SELECT protection into protec FROM ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
IF protec=0 THEN ok1="true";
END IF;

IF ok1 or ok2 THEN
	-- archivage du sujet modifié
	INSERT INTO BACKSUJET 
	(NUMBACKUP,NUMSUJET,AUTEUR,TITRE,DATEMODIF,AUTEURMODIF,TEXTE)
	SELECT (OLD.NUMBACKUP, OLD.NUMSUJET, OLD.AUTEUR,OLD.TITRE, OLD.DATEMODIF, 
	OLD.AUTEURMODIF, OLD.TEXTE)
	FROM ALLSUJET
	WHERE NUMSUJET=NEW.NUMSUJET;

	-- test sur le nombre de sauvegarde du sujet
	-- si >10 on supprime le 11ème pour n'en garder que 10
	SELECT COUNT(numbackup) INTO nbrbackup from lgpbak WHERE old.numsujet=new.numsujet GROUP BY numsujet;
		IF nbrbackup>10 THEN
		DELETE FROM lgpbak WHERE numbackup=MIN(numbackup) AND old.numsujet=new.numsujet;
		END IF;

	-- update du sujet 
	-- avec date de modif + update de AUTEURMODIF + incrémentation du compteur NUMBACKUP
	UPDATE ALLSUJET SET 
		OLD.titre = NEW.titre ,
		OLD.datemodif = current_date,
		OLD.auteurmodif = current_user ,
		OLD.numbackup = OLD.numbackup+1,
		OLD.texte = NEW.texte
		WHERE OLD.NUMSUJET = NUMSUJET;
		RETURN NEW;

	ELSE
	RAISE WARNING 'L''utilisateur % n''est pas autorise à modifier le sujet numero %', current_user, NEW.numsujet;
	RETURN NULL;
	END IF;
END;
$$ LANGUAGE plpgsql;

l'erreur :
postgres=> UPDATE ALLSUJET SET titre = 'test UPDATE1' WHERE numsujet=2;

ERREUR:  INSERT a plus de colonnes cibles que d'expressions
LIGNE 2 : (NUMBACKUP,NUMSUJET,AUTEUR,TITRE,DATEMODIF,AUTEURMODIF,TEXTE...
                     ^
ASTUCE : La source d'insertion est une expression de ligne contenant le même nombre
de colonnes que celui attendu par INSERT. Auriez-vous utilisé des parenthèses
supplémentaires ?
REQUÊTE : INSERT INTO BACKSUJET
(NUMBACKUP,NUMSUJET,AUTEUR,TITRE,DATEMODIF,AUTEURMODIF,TEXTE)
SELECT (OLD.NUMBACKUP, OLD.NUMSUJET, OLD.AUTEUR,OLD.TITRE, OLD.DATEMODIF,
OLD.AUTEURMODIF, OLD.TEXTE)
FROM ALLSUJET
WHERE NUMSUJET=NEW.NUMSUJET
CONTEXTE : PL/pgSQL function "fonction_autobackup" line 20 at instruction SQL


toutes les parenthèses ouvertes sont fermées, et sans parenthèses ça veut pas marcher non plus...
un indice ?

#14 Général » un dernier trigger pour la route » 24/01/2012 21:17:00

Morby
Réponses : 27

salut à tous, le Morby des montagnes est de retour avec un nouveau trigger

mes tables :

CREATE TABLE LGPUTILS
       (NUMUSER SERIAL,
        NOM VARCHAR(25) PRIMARY KEY,
	PASSWORD VARCHAR(25) NOT NULL,
	NBARTICLECREE INTEGER DEFAULT '0');

CREATE VIEW LGPUSERNEW AS SELECT * FROM LGPUTILS;
grant select on LGPUSERNEW to public;
grant insert on LGPUSERNEW to public;
grant update on LGPUSERNEW to public;
grant delete on LGPUSERNEW to public;
CREATE TABLE LGPSUJET
       (NUMSUJET SERIAL PRIMARY KEY,
	AUTEUR VARCHAR(25) REFERENCES LGPUTILS (NOM),
	TITRE VARCHAR NOT NULL,
	DATEPARUTION DATE DEFAULT current_date,
	DATEMODIF DATE DEFAULT current_date,
	AUTEURMODIF VARCHAR(25) REFERENCES LGPUTILS (NOM),
	NUMBACKUP INTEGER DEFAULT '1',
	NBVUE INTEGER DEFAULT '0',
	TEXTE VARCHAR NOT NULL,
	PROTECTION INTEGER DEFAULT '1'	);

CREATE VIEW ALLSUJET AS SELECT * FROM LGPSUJET;
grant select on ALLSUJET to public;
grant insert on ALLSUJET to public;
grant update on ALLSUJET to public;
CREATE TABLE LGPAUTH
       (NUMSUJET INTEGER REFERENCES LGPSUJET (NUMSUJET),
        AUTEUR VARCHAR(25) REFERENCES LGPUTILS (NOM),
	AUTORISEDTOMODIF VARCHAR(25) );

ALTER TABLE LGPAUTH ADD PRIMARY KEY ( NUMSUJET, AUTORISEDTOMODIF);
grant insert on LGPAUTH to public;
grant delete on LGPAUTH to public;
grant select on LGPAUTH to public;

CREATE VIEW AUTORIS AS SELECT * FROM LGPAUTH;
grant insert on AUTORIS to public;
grant delete on AUTORIS to public;
grant select on AUTORIS to public;
DROP TABLE LGPBAK CASCADE;
CREATE TABLE LGPBAK
	(NUMBACKUP INTEGER,
	NUMSUJET INTEGER REFERENCES LGPSUJET (NUMSUJET),
	AUTEUR VARCHAR(25) REFERENCES LGPUTILS (NOM),
	TITRE VARCHAR,
	DATEMODIF DATE,
	AUTEURMODIF VARCHAR(25),
	TEXTE VARCHAR);

CREATE VIEW BACKSUJET AS SELECT * FROM LGPBAK;
grant select on BACKSUJET to public;
grant insert on BACKSUJET to public;
grant delete on BACKSUJET to public;

_____________________________________________________________


et voici le trigger qui me pose problème :

---- TRIGGER = update sur les sujets publiés
CREATE OR REPLACE FUNCTION fonction_autobackup() RETURNS TRIGGER AS $$
DECLARE
ok1 boolean;
ok2 boolean;
protec integer;
nbrbackup integer;
BEGIN
-- ****** verification de propriete du sujet ou de l'autorisation de modification *******
-- verifie si le current_user est l'auteur de ce sujet
SELECT (current_user = auteur) INTO ok1 FROM  ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
-- verifier si le current_user est autorisé à modifier ce sujet
SELECT (current_user = autorisedtomodif) INTO ok2 FROM AUTORIS WHERE NUMSUJET = NEW.NUMSUJET;
--- vérifie si la PROTECTION est désactivée (valeur à 0)
SELECT protection into protec FROM ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
IF protec=0 THEN ok1="true";
END IF;

IF ok1 or ok2 THEN
	-- *** archivage de l'ancienne version du sujet dans la table Backup *** 
	INSERT INTO BACKSUJET 
	(NUMSUJET,AUTEUR,TITRE,DATEMODIF,AUTEURMODIF,NUMBACKUP,TEXTE)
	SELECT (OLD.NUMSUJET, OLD.AUTEUR,OLD.TITRE, OLD.DATEMODIF, 
	OLD.AUTEURMODIF, OLD.NUMBACKUP, OLD.TEXTE)
	FROM ALLSUJET
	WHERE NUMSUJET=NEW.ALLSUJET;

	-- *** test sur le nombre de sauvegarde du sujet ***
	-- si >10 on supprime le 11ème pour n'en garder que 10
	SELECT COUNT(numbackup) INTO nbrbackup from lgpbak WHERE old.numsujet=new.numsujet GROUP BY numsujet;
		IF nbrbackup>10 THEN
		DELETE FROM lgpbak WHERE numbackup=MIN(numbackup) AND old.numsujet=new.numsujet;
		END IF;

	-- *** update du sujet dans la table ALLSUJET avec les nouvelles valeurs***
	--   + date de modif + update de AUTEURMODIF + incrémentation du compteur NUMBACKUP
	UPDATE ALLSUJET SET 
		OLD.titre = NEW.titre ,
		OLD.datemodif = current_date,
		OLD.auteurmodif = current_user ,
		OLD.numbackup = OLD.numbackup+1,
		OLD.texte = NEW.texte
		WHERE OLD.NUMSUJET = NEW.NUMSUJET;
		RETURN NEW;

	ELSE
	RAISE WARNING 'L''utilisateur % n''est pas autorise à modifier le sujet numero %', current_user, NEW.numsujet;
	RETURN NULL;
	END IF;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER fonction_autobackup 
INSTEAD OF UPDATE ON ALLSUJET
FOR EACH ROW EXECUTE PROCEDURE fonction_autobackup();

le message d'erreur :

postgres=> UPDATE ALLSUJET SET titre = 'test UPDATE1' WHERE numsujet=2;

ERREUR:  l'enregistrement « new » n'a pas de champs « allsujet »
CONTEXTE : SQL statement "INSERT INTO BACKSUJET 
(NUMSUJET,AUTEUR,TITRE,DATEMODIF,AUTEURMODIF,NUMBACKUP,TEXTE)
SELECT (OLD.NUMSUJET, OLD.AUTEUR,OLD.TITRE, OLD.DATEMODIF, 
OLD.AUTEURMODIF, OLD.NUMBACKUP, OLD.TEXTE)
FROM ALLSUJET
WHERE NUMSUJET=NEW.ALLSUJET"
fonction PL/pgsql « fonction_autobackup », ligne 20 à instruction SQL

je dois rendre mon projet demain, je bosse là dessus depuis 17h et je tourne en rond, la panique me gagne doucement et je ne comprend pas le message d'erreur

help please

#16 Général » nouveau probleme de syntaxe » 20/01/2012 02:53:16

Morby
Réponses : 2

rebonjour tout le monde, j'arrive au bout de mon projet pgsql, il ne me reste plus qu'un trigger à faire. Les aides précédentes m'ont été d'un grand secours pour comprendre leur mécanisme et leur syntaxe.

cette fois j'attaque avec une requete récalcitrante : je désire récupérer certaines colonnes de ma table "sujets", pour les insérer en une fois dans une table "backup"

		INSERT INTO BACKSUJET 
		(NUMSUJET,AUTEUR,TITRE,DATEMODIF,AUTEURMODIF,NUMBACKUP,TEXTE)
		AS SELECT (OLD.NUMSUJET, OLD.AUTEUR,OLD.TITRE, OLD.DATEMODIF, 
		OLD.AUTEURMODIF, OLD.NUMBACKUP, OLD.TEXTE)
		FROM ALLSUJET
		WHERE OLD.NUMSUJET=NEW.ALLSUJET;

ERREUR:  erreur de syntaxe sur ou près de « AS »
LIGNE 3 : AS SELECT (OLD.NUMSUJET, OLD.AUTEUR,OLD.TITRE, OLD.DATEMODIF...

j'ai essayé de mettre/enlever/déplacer mes parenthèses mais apparemment le prb ne vient pas de là. bref, j'y ai passé ma soirée et pas trouvé grand chose sur google pour me dépanner mis à part des docs sur les vues en cherchant avec les mots clé "postgresql" +"as select"
sad

un indice ?

#17 Re : Général » encore un probleme de trigger » 19/01/2012 13:08:00

super génial, ça fonctionne parfaitement
tout mes remerciements pour ce forumo-guidage de qualité

#18 Re : Général » encore un probleme de trigger » 19/01/2012 12:30:18

quel boulet je suis...
Bourvil aurait dit un truc du genre : effectivement ça va marcher bcp moins bien ^^

le trigger est maintenant opérationnel et fonctionnel, encore merci pour ta patience smile

encore une petite question, d'ordre cosmétique cette fois :
pour le cas de figure ou current_user est différent de new.auteur, est-il possible d'afficher dans le prompt un message de type "nous n'êtes pas autorisé à donner des droits d'accès sur ce n° de sujet " ?

#19 Re : Général » encore un probleme de trigger » 19/01/2012 11:17:54

j'ai intégré la fonction TG_OP

CREATE FUNCTION fonction_insert_autorisation() RETURNS TRIGGER AS $$
DECLARE
ok boolean;
BEGIN
SELECT (current_user = auteur) INTO ok FROM  ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
IF ok THEN
INSERT INTO LGPAUTH (NUMSUJET,AUTEUR,AUTORISEDTOMODIF) VALUES
	(NEW.NUMSUJET,
	current_user,
	NEW.AUTEUR);
		IF (TG_OP = 'UPDATE') THEN
		RETURN NEW;
		ELSIF (TG_OP = 'DELETE') THEN
		RETURN OLD;
		END IF;
	ELSE RETURN NULL;
	END IF;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER fonction_insert_autorisation 
INSTEAD OF INSERT OR DELETE ON AUTORIS
FOR EACH ROW EXECUTE PROCEDURE fonction_insert_autorisation();

EDIT : j'ai finalement compris pourquoi je partais en boucle...l'insertion effectuée par le trigger a pour effet de redéclencher le meme trigger ^^
en mettant le nom de la table originale plutôt que le nom de la vue pour l'insert ça corrige le problème smile

reste maintenant un problème de syntaxe foirée pour mon TG_OP...
ERREUR:  le contrôle a atteint la fin de la procédure trigger sans RETURN
CONTEXTE : fonction PL/pgsql « fonction_insert_autorisation »

#20 Re : Général » encore un probleme de trigger » 19/01/2012 10:27:50

j'ai suivi vos conseils et me suis référé à la doc, effectivement ça simplifie les choses de zapper la RULE

j'ai donc modifié ma fonction/trigger comme ceci :

CREATE FUNCTION fonction_insert_autorisation() RETURNS TRIGGER AS $$
DECLARE
ok boolean;
BEGIN
SELECT (current_user = auteur) INTO ok FROM  ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
IF ok THEN
INSERT INTO AUTORIS (NUMSUJET,AUTEUR,AUTORISEDTOMODIF) VALUES
	(NEW.NUMSUJET,
	current_user,
	NEW.AUTEUR);
	RETURN NEW;
	END IF;
RETURN NULL;	
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER fonction_insert_autorisation ON AUTORIS;
CREATE TRIGGER fonction_insert_autorisation 
INSTEAD OF INSERT ON AUTORIS
FOR EACH ROW EXECUTE PROCEDURE fonction_insert_autorisation();

il semblerait que je sois obligé de faire un autre trigger/fonction en cas de DELETE sur la table (avec un return OLD si j'ai bien tout compris)


ceci étant, j'ai toujours le même problème d'erreur au déclenchement du trigger lorsque j'essaye de faire un INSERT sur la vue :

PL/pgSQL function "fonction_insert_autorisation" line 7 at instruction SQL
instruction SQL « INSERT INTO AUTORIS (NUMSUJET,AUTEUR,AUTORISEDTOMODIF) VALUES
(NEW.NUMSUJET,
current_user,
NEW.AUTEUR) »

ce message d'erreur semble boucler sur lui même, il rempli toute la console, j'en déduis que c'est ma boucle qui déconne.

comme décrit précédemment, j'ai essayé de modifier la fin de la requete en :
...
RETURN NEW;
ELSE
RETURN NULL;
END IF;   
END;

mais ça ne change rien au résultat sad

#21 Re : Général » encore un probleme de trigger » 19/01/2012 09:44:53

merci mon cher mais vous me parlez un langage qui m'est en grande partie étranger ^^

en effet je suis bien sous PostgreSQL 9.1 et c'est un nouveau développement, dans le cadre d'un projet que je dois remettre la semaine prochaine et qui comptera pour ma note finale en mars prochain (formation accélérée). En ce qui me concerne, je suis grand débutant, ya encore 3 mois j'ignorais tout des bases de données. En cours, on a pas du tout abordé les triggers sous Postgres, on a eu juste 2h de cours sur les triggers sous Oracle + un TP que je ne suis pas parvenu à faire ayant du retard sur les précédant. ça explique surement en grande partie mon inélégance dans mon approche pour résoudre mon problème.

Donc d'après vous je peux me passer de la règle qui autorise les inserts sur la vue ?
et seulement faire un trigger/fonction qui gèrera à la fois l'autorisation d'insert sur la vue et la vérification auteur=current_user ?

puis-je abuser de votre gentillesse et vous demander un exemple de code svp ?
car pour moi, un petit dessin vaut souvent mieux qu'un long discours ^^

#22 Re : Général » encore un probleme de trigger » 19/01/2012 08:30:05

merci pour ton aide
effectivement je n'avais pas du tout pensé à utiliser un booléen, et quand bien même cette syntaxe m'est complètement inconnue

voici donc la nouvelle mouture de mon trigger :

CREATE FUNCTION fonction_verif_autorisation() RETURNS TRIGGER AS $$
DECLARE
ok boolean;
BEGIN
SELECT (current_user = auteur) INTO ok FROM  ALLSUJET WHERE NUMSUJET = NEW.NUMSUJET;
IF ok THEN
INSERT INTO AUTORIS (NUMSUJET,AUTEUR,AUTORISEDTOMODIF) VALUES
	(NEW.NUMSUJET,
	current_user,
	NEW.AUTEUR);
	RETURN NEW;
	END IF;
RETURN NULL;	
END;
$$ LANGUAGE plpgsql;


CREATE TRIGGER fonction_verif_autorisation BEFORE INSERT OR DELETE ON LGPAUTH
FOR EACH ROW EXECUTE PROCEDURE fonction_verif_autorisation();

et maintenant j'ai une nouvelle erreur :

PL/pgSQL function "fonction_verif_autorisation" line 7 at instruction SQL
instruction SQL « INSERT INTO AUTORIS (NUMSUJET,AUTEUR,AUTORISEDTOMODIF) VALUES
(NEW.NUMSUJET,
current_user,
NEW.AUTEUR) »

j'ai essayé de modifier la fin de la requete en :
...
RETURN NEW;
ELSE
RETURN NULL;
END IF;   
END;

mais rien n'y fait, je ne trouve pas d'où vient l'erreur sad

#23 Général » encore un probleme de trigger » 18/01/2012 21:21:47

Morby
Réponses : 12

salut tout le monde, de retour avec un autre problème de trigger sur mon mini-wiki

j'ai une table d'utilisateurs :

DROP TABLE LGPUTILS CASCADE;
CREATE TABLE LGPUTILS
       (NUMUSER SERIAL,
        NOM VARCHAR(25) PRIMARY KEY,
	PASSWORD VARCHAR(25) NOT NULL,
	NBARTICLECREE INTEGER DEFAULT '0'
	);

-- droits d'accès pour la séquence (SERIAL)
GRANT USAGE on lgputils_numuser_seq to public;

--création d'une vue LGPUSERNEW qui permet de voir tous les attributs de la table
DROP VIEW LGPUSERNEW;
CREATE VIEW LGPUSERNEW AS SELECT * FROM LGPUTILS;

-- donne les droits sur la vue LGPUSERNEW
grant select on LGPUSERNEW to public;
grant insert on LGPUSERNEW to public;
grant update on LGPUSERNEW to public;
grant delete on LGPUSERNEW to public;


-- création d'une règle sur la vue "LGPUSERNEW"
-- permettant l'insertion de nouveaux utilisateurs avec automatisme : nom = compte utilisateur
DROP RULE usernew_insert on LGPUSERNEW CASCADE;
CREATE RULE usernew_insert AS ON INSERT TO LGPUSERNEW DO INSTEAD 
	INSERT INTO LGPUTILS VALUES 
	(default, 
	current_user, 
	NEW.PASSWORD);

une table de sujets :

DROP TABLE LGPSUJET CASCADE;
CREATE TABLE LGPSUJET
       (NUMSUJET SERIAL PRIMARY KEY,
	AUTEUR VARCHAR(25) REFERENCES LGPUTILS (NOM),
	TITRE VARCHAR NOT NULL,
	DATEPARUTION DATE DEFAULT current_date,
	DATEMODIF DATE DEFAULT current_date,
	AUTEURMODIF VARCHAR(25) REFERENCES LGPUTILS (NOM),
	NUMBACKUP INTEGER DEFAULT '1',
	NBVUE INTEGER DEFAULT '0',
	TEXTE VARCHAR NOT NULL,
	PROTECTION INTEGER DEFAULT '1'	);

-- droits d'accès pour la séquence (SERIAL)
GRANT USAGE on lgpsujet_numsujet_seq to public;

-- création d'une vue qui permet de voir tous les sujets de la table
DROP VIEW ALLSUJET;
CREATE VIEW ALLSUJET AS SELECT * FROM LGPSUJET;
grant select on ALLSUJET to public;
grant insert on ALLSUJET to public;

-- création d'une règle qui permet l'insertion de nouveaux sujets à travers la vue ALLSUJET
DROP RULE sujet_insert ON ALLSUJET;
CREATE RULE sujet_insert AS ON INSERT TO ALLSUJET DO INSTEAD
    INSERT INTO LGPSUJET (auteur, titre, texte) VALUES
    (current_user,
    NEW.TITRE,
    NEW.TEXTE);

et enfin une table pour les autorisations de modification des sujets :

DROP TABLE LGPAUTH CASCADE;	
CREATE TABLE LGPAUTH
       (NUMSUJET INTEGER REFERENCES LGPSUJET (NUMSUJET),
        AUTEUR VARCHAR(25) REFERENCES LGPUTILS (NOM),
	AUTORISEDTOMODIF VARCHAR(25));

-- création d'une vue sur la table LGPAUTH
CREATE VIEW AUTORIS AS SELECT * FROM LGPAUTH;
grant select on AUTORIS to public;
grant insert on AUTORIS to public;
grant delete on AUTORIS to public;

-- création d'une règle qui permet l'insertion de nouvelles autorisations
-- à placer dans un trigger "before", qui vérifie que auteur = current_user
DROP RULE donne_autorisation ON AUTORIS;
CREATE RULE donne_autorisation AS ON INSERT TO AUTORIS DO INSTEAD
    INSERT INTO LGPAUTH (NUMSUJET,AUTEUR,AUTORISEDTOMODIF) VALUES
	(NEW.NUMSUJET,
	current_user,
	NEW.AUTEUR);

cette table référence un numéro de sujet + le nom de son auteur + le nom de l'utilisateur autorisé à modifier le sujet en colonne 1

je désire donc créer un trigger qui va vérifier que le current_user qui fait l'insert dans cette table est bien l'auteur du n° de sujet à qui il veut donner l'autorisation de modification à une autre utilisateur
pour bien faire les choses, faudrait aussi vérifier que l'utilisateur à qui on veut donner l'autorisation est bien présent dans la table des utilisateurs...

voici le trigger que j'ai pondu :

DROP FUNCTION fonction_verif_autorisation() CASCADE;
CREATE FUNCTION fonction_verif_autorisation() RETURNS TRIGGER AS $$
BEGIN
IF (NEW.NUMSUJET = NUMSUJET FROM (SELECT NUMSUJET FROM ALLSUJET WHERE auteur=current_user))
THEN
INSERT INTO LGPAUTH (NUMSUJET,AUTEUR,AUTORISEDTOMODIF) VALUES
	(NEW.NUMSUJET,
	current_user,
	NEW.AUTEUR);
	RETURN NEW;
	END IF;
RETURN NULL;
	END;
$$ LANGUAGE plpgsql;

DROP TRIGGER fonction_verif_autorisation ON lgpsujet;
CREATE TRIGGER fonction_verif_autorisation BEFORE INSERT OR DELETE ON LGPAUTH
FOR EACH ROW EXECUTE PROCEDURE fonction_verif_autorisation();

La fonction me fait cette erreur quand j'essaye de l'enregistrer :
ERREUR:  erreur de syntaxe sur ou près de « FROM »
LIGNE 3 : IF (NEW.NUMSUJET = NUMSUJET FROM (SELECT NUMSUJET FROM ALLSU...
                                                              ^

donc problème de syntaxe sur ma requete mais je ne m'en sort pas
tout coup de main est bienvenu, merci

#24 Re : Général » probleme de noob : requete et triggers » 12/01/2012 13:19:30

yessssssssss ça marche ^^
super, encore un grand merci pour ton aide, c'était franchement pas facile pour un noob comme moi tongue

sujet clos

#25 Re : Général » probleme de noob : requete et triggers » 12/01/2012 11:39:16

avec un RETURN sans S

CREATE FUNCTION fonction_increment_crearticle() RETURN NEW AS $$
BEGIN
UPDATE LGPUSERNEW 
	SET NBARTICLECREE = NBARTICLECREE+1
	WHERE nom=current_user;
END;
$$ LANGUAGE plpgsql;

ERREUR:  erreur de syntaxe sur ou près de « RETURN »
LIGNE 1 : CREATE FUNCTION fonction_increment_crearticle() RETURN NEW A...
                                                                                         ^

------------------------
avec un RETURNS

CREATE FUNCTION fonction_increment_crearticle() RETURNS NEW AS $$
BEGIN
UPDATE LGPUSERNEW 
	SET NBARTICLECREE = NBARTICLECREE+1
	WHERE nom=current_user;
END;
$$ LANGUAGE plpgsql;

ERREUR:  le type « new » n'existe pas
sad


autre question : dans le trigger, est-ce que la mention "for each row" est obligatoire ?
les inserts de sujets se font à l'unité, et le trigger s'effectue à l'unité aussi, je voudrais pas que le compteur soit incrémenté pour tous les utilisateurs de la table des utilisateurs

Pied de page des forums

Propulsé par FluxBB