PostgreSQL
La base de données la plus sophistiquée au monde.

Ouverture de session

Navigation

Contactez-nous

Administration du site :
"equipe chez postgresqlfr point org"

Contact presse :
"fr chez postgresql point org"

Contact association :
"bureau chez postgresqlfr point org"

Questions PostgreSQL :
 IRC :
  serveur irc.freenode.net
  canal #postgresqlfr

Recherche

Accéder aux archives

« Octobre 2008  
Lun Mar Mer Jeu Ven Sam Dim
  2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31  

Syndication

Flux XML

Sondage

Quelle est la version de PostgreSQL la plus répandue sur vos serveurs ?
8.3
10%
8.2
42%
8.1
40%
8.0
2%
7.4
6%
7.3 ou antérieure
0%
Nombre de votes: 48

Trigger pour "UPDATE IF FOUND sinon un INSERT"

Technique - général | Trigger pour "UPDATE IF FOUND sinon un INSERT"

Par ducteil le 13/01/2007 - 04:12

Bonjour

Je suis en plpgsql et j'aimerais que lors d'un simple UPDATE [fichier] SET champ1 = var1, champ2 = var2, etc… Where cle = varcle;
la base vérifie si l'enregistrement existe et de le créer le cas échéant.
D'après ce que j'ai lu il faudrait passer par un trigger, mais après moult essais rien de fonctionne.

J'utilise en fait postgres comme base de transfert de données; en ce moment mon application doit vérifier pour chaque enregistrement si il existe, avant de le modifier ou de l'ajouter selon (2 requètes par enregistrement à transferer).

Pouvez-vous m'aider ?
Le sujet est traité un peu partout mais malgré tout, je ne trouve pas la solution.

NB : version Postgresql 8.14

Dernière trouvaille :
BEGIN TRANSACTION;
SAVEPOINT sp1;
INSERT INTO [] VALUES ('07-03-2006' ,'00:00:00', 'mon titre', 'mon texte' );
ROLLBACK TO sp1;
UPDATE [] SET titre='mon titre', texte='mon texte',heure='00:00:00'
WHERE date = '07-03-2006';
COMMIT;
Ne fonctionne pas ...
///ERREUR: une clé dupliquée rompt la contrainte unique «date»

Cordialement

Olivier DUCTEIL
http://www.2amath.fr

Options d'affichage des commentaires

Sélectionnez la méthode d'affichage des commentaires que vous préférez, puis cliquez sur "Sauvegarder les paramètres" pour activer vos changements.

Précision ?

SAS/ = 14 Janvier, 2007 - 16:03

Bonjour,

Pourriez-vous être plus précis ? Je ne comprends pas vraiment ce que vous cherchez à faire. Je ne vois en effet pas bcp de rapports entre la solution proposée et la question initiale.

Librement,
Stéphane Schildknecht
dalibo
PostgreSQLFr


Trigger pour "UPDATE IF FOUND sinon un INSERT"

ducteil/ = 14 Janvier, 2007 - 18:59

Bonjour

En effet, mon problème peut se résoudre de deux façons :
+ soit, j'insére un nouvel élément dans un fichier, si l'élément existe déjà, le mettre à jour.
+ soit modifier un élément, si il n'existe pas le créer.
Je pense que l'on doit passer par un trigger, car la solution via une transaction avec gestion d'erreur ne semble pas fonctionner (http://traduc.postgresqlfr.org/pgsql-8.1.4-fr/sql-update.html tout en bas !).
J'espère avoir été plus clair

Cordialement
Olivier DUCTEIL


Faire une petite fonction psq

sparky/ = 15 Janvier, 2007 - 11:51

Faire une petite fonction psql avec un parametre de type rowtype%TABLE

exemple
-- existe ??
select count(*) into nCount from TABLE where cond

if count = 0 then
-- n'existe pas, je fais insert
else
-- existe je fais update
end if


Le Trigger ne donne pas de résultat...

ducteil/ = 16 Janvier, 2007 - 02:16

Bonjour

J'ai bien compris la mécanique (if then else) mais pratiquement je n'y arrive pas.
-----
--DROP TABLE matable;
CREATE TABLE matable
(
date date NOT NULL,
heure time,
titre char(50),
texte text,
CONSTRAINT date_matable PRIMARY KEY (date)
);
CREATE OR REPLACE FUNCTION mise_a_jour() RETURNS "trigger" AS
$BODY$
DECLARE

matable_ligne matable%ROWTYPE;
BEGIN
SELECT * INTO matable_ligne FROM matable WHERE date = NEW.date;
IF (matable_ligne == null) THEN
INSERT INTO matable VALUES (NEW.date,NEW.heure, NEW.titre, NEW.texte);
RETURN NULL;
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
CREATE TRIGGER trigger_matable BEFORE UPDATE ON matable FOR EACH ROW EXECUTE PROCEDURE mise_a_jour();

--- On exécute la procédure ----
UPDATE matable SET date='07-04-2006', titre='nouveau titre', texte='mon texte++--',heure='00:00:00' WHERE date='07-04-2006';

--- On vérifie ----
SELECT * FROM matable;
-----
Pas d'enregistrement effectué... je ne vois pas pourquoi.

Cordialement
Olivier DUCTEIL


Oui l'erreur est ici

sparky/ = 16 Janvier, 2007 - 13:01

Oui l'erreur est ici
SELECT * INTO matable_ligne FROM matable WHERE date = NEW.date;
IF (matable_ligne == null) THEN
INSERT INTO matable VALUES (NEW.date,NEW.heure, NEW.titre, NEW.texte);

soit tu fais
if matable_ligne is NULL Then ...

soit tu fais
if FOUND = False then

Attention plpgsql^n'est pas du C, donc pas de double = pour les tests, ni pas de parenthèse ;-)

Je préfère faire un count, ça marchera même sur une 7 :-)


Le Trigger UPDATE => INSERT

ducteil/ = 18 Janvier, 2007 - 18:05

Bonjour
Je n’ai toujours aucun ajout après mon update.
1 - Est-ce les « NEW.*» ne changent pas de valeur après le SELECT de la procédure ?
Dans ce cas, ils seront tous NULL, pour l'insertion suivante.
2 - Est-ce que la procédure "comprend" bien que c'est la table 'matable' et non une variable "locale" qu'il faut affecter après un INSERT INTO ?
3 - Peut-on modifier la table sur laquelle s'exécute le trigger ?
Les modifs

(...)
DECLARE
matable_ligne matable%ROWTYPE;

BEGIN
SELECT * INTO matable_ligne FROM matable WHERE date = NEW.date;
IF matable_ligne IS NULL THEN
INSERT INTO matable VALUES (current_date,NEW.heure, NEW.titre, NEW.texte);
RETURN NULL;
ELSE
RETURN NEW;
END IF;
END;
(...)

J'ai mis « current_date » à la place de « NEW.date » en cas où ma première assertion soit vraie.

[NB : Merci pour le temps passé à la résolution de ce problème]

Cordialement
Olivier
http://www.2amath.fr


Tu sais, je pense Ă  un truc:

sparky/ = 19 Janvier, 2007 - 12:39

Tu sais, je pense à un truc: tu fais update before, or l'update ne sera jamais éxécuté pour la simple raison qu'il n'y a aucune ligne à updater, le mieux alors d'utiliser les rules ou de passer par une fonction

voir ici http://docs.postgresqlfr.org/pgsql-8.1.6-fr/sql-createrule.html

Pourrais utiliser raise notice

exemple :
DECLARE
matable_ligne matable%ROWTYPE;

BEGIN
SELECT * INTO matable_ligne FROM matable WHERE date = NEW.date;
IF matable_ligne IS NULL THEN
raise notice 'Aucune ligne trouvée on fait insert';
INSERT INTO matable VALUES (current_date,NEW.heure, NEW.titre, NEW.texte);
RETURN NULL;
ELSE
raise notice 'ligne trouvée on fait un update';
RETURN NEW;
END IF;
END;


© PostgreSQLFr, tous droits rĂ©servĂ©s.
Site déclaré à la CNIL sous le numéro 1074678, conformément à la Loi en vigueur.