Vous n'êtes pas identifié(e).

#1 01/02/2012 22:55:08

msxsan
Membre

Vue, régle et clé primaire

Bonjour à tous,

C'est mon premier post ;-)

A l'occasion d'un développement, je découvre Postgresql et j'ai un problème avec les vues. J'ai besoin d'utiliser des vues modifiables composées de plusieurs tables. Lors d'un INSERT, il me faut alimenter une première table et ensuite une seconde avec la valeur (autoincrémentée) de la clé primaire de la première table.

En consultant les docs, j'ai bien compris qu'il faut définir une règle sur la vue, redéfinir le INSERT et exécuter deux requêtes (en les séparant par un ";"). Mais comment récupérer la valeur de la clé primaire de la première table pour le second INSERT ? Il y a bien RETURNING mais comment l'utiliser dans ce contexte ?

Merci d'avance pour votre aide
Olivier

Hors ligne

#2 01/02/2012 23:57:17

gleu
Administrateur

Re : Vue, régle et clé primaire

Si la valeur de la clé primaire est gérée automatiquement par une séquence, il est possible d'utiliser la fonction currval pour connaître la nouvelle valeur de la séquence, donc en fait la valeur du dernier élément inséré.


Guillaume.

Hors ligne

#3 02/02/2012 09:03:30

msxsan
Membre

Re : Vue, régle et clé primaire

Merci pour cette réponse,

ok, mais cette technique ne peut elle pas poser de problèmes en cas d'accès multiples sur la première table ?

Lorsque 2 requêtes SQL sont lancées à la suite au sein d'une règle, leur exécution est-elle exclusive ? Supposons qu'une première requête sur la vue déclenche le INSERT, le code SQL (INSERT dans la la table A et INSERT (avec curval(seq_table_A)) dans la table B est lancé. Si durant ce laps de temps, une nouvelle requête INSERT est fait sur la table A, le résultat de curval(sql_table_A) ne risque t'il pas d'être erroné ? Faut il utiliser une transaction (BEGIN et COMMIT) autour des deux requêtes pour préserver leur contexte ?

Olivier ;-)

Hors ligne

#4 02/02/2012 10:28:55

msxsan
Membre

Re : Vue, régle et clé primaire

Pour tester la solution currval(), j'ai écrit la règle suivante :

CREATE RULE insertEquipe AS ON INSERT TO listeequipes DO INSTEAD (
    INSERT INTO equipes(cle,cle_theme,siteweb,description) VALUES(default,NEW.cle_theme,new.siteweb,NEW.description);
    INSERT INTO noms(cle,cle_equipe,nom,debut) VALUES(default,CURRVAL('equipes_cle_seq'),NEW.nom,NEW.debut);
);

Le code SQL ne fonctionne pas. J'obtiens différents messages d'erreur qui semble provenir de la syntaxe de la règle.

Error : ERROR:  syntax error at end of input
LINE 2: ...n) VALUES(default,NEW.cle_theme,new.siteweb,new.description)
                                                                       ^
Error : ERROR:  NEW used in query that is not in a rule

Error : ERROR:  syntax error at or near ")"
LINE 1: )
        ^

Pourtant dans le doc de Postgresql, il est bien écrit que l'on peut placer différentes commandes dans une règle.

CREATE [ OR REPLACE ] RULE nom as on evenement
    TO table [ where condition ]
    DO [ ALSO | INSTEAD ] { NOTHING | commande | ( commande ; commande ... ) }

Une idée ? merci d'avance

Olivier

PS: j'ai un serveur 8.3 (au cas où...)

Hors ligne

#5 02/02/2012 13:35:20

msxsan
Membre

Re : Vue, régle et clé primaire

J'ai résolu mon problème. En fait, ce n'était pas la requête en elle-même mais Navicat. j'utilise ce logiciel pour travailler avec la base de données et c'est lui qui générait les messages d'erreur. Visiblement, il ne supporte pas plusieurs requêtes SQL dans la définition d'une règle.

Par contre, avec pgAdmin III, ça fonctionne parfaitement.

Olivier ;-)

Hors ligne

#6 02/02/2012 14:32:58

dverite
Membre

Re : Vue, régle et clé primaire

msxsan a écrit :

ok, mais cette technique ne peut elle pas poser de problèmes en cas d'accès multiples sur la première table ?

Lorsque 2 requêtes SQL sont lancées à la suite au sein d'une règle, leur exécution est-elle exclusive ? Supposons qu'une première requête sur la vue déclenche le INSERT, le code SQL (INSERT dans la la table A et INSERT (avec curval(seq_table_A)) dans la table B est lancé. Si durant ce laps de temps, une nouvelle requête INSERT est fait sur la table A, le résultat de curval(sql_table_A) ne risque t'il pas d'être erroné ? Faut il utiliser une transaction (BEGIN et COMMIT) autour des deux requêtes pour préserver leur contexte ?

Non l'exécution n'est pas exclusive mais ça ne change rien au résultat de currval('sequence') puisque c'est la valeur pour la session en cours.

Hors ligne

Pied de page des forums