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

Auto incrémenter un champs dans une clé primaire à deux champs en fonction du premier.

Technique - général | Auto incrémenter un champs dans une clé primaire à deux champs en fonction du premier.

Par ioguix le 20/03/2006 - 14:44

Bonjour,

J'aimerais pouvoir créer dans une table une clé primaire formée de deux champs dont un auto-incrémenté en fonction du premier.

Par exemple :
personne, auto
sam, 1
sam, 2
sam, 3
ludo, 1
luc, 1
luc, 2

Dans ce cas là, j'aimerai que le champs auto s'incrémente automatiquement...

Savez vous comment faire ou m'indiquer des pistes potentielles ?

D'avance, merci.

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.

utiliser un trigger http://

sparky/ = 20 Mars, 2006 - 15:32

utiliser un trigger
http://docs.postgresqlfr.org/pg-8.1.2/trigger-example.html
et en langage plpgsql
http://docs.postgresqlfr.org/pg-8.1.2/plpgsql.html
Le plus simple, après un insert calcul de la clef 2 et insertion ;)


Pourquoi un trigger alors qu'

Christophe Chauvet/ = 20 Mars, 2006 - 15:53

Pourquoi un trigger alors qu'avec MAX() + 1 lors de l'insert cela fonctionne (un COUNT() + 1) doit aussi fonctionner .

Cordialement.

Christophe Chauvet
http://kryskool.org/


reBonjour, J'ai créé cet

ioguix/ = 20 Mars, 2006 - 19:05

reBonjour,

J'ai créé cette requête qui marche bien sur l'idée de kryskool :

INSERT INTO test (nom, id) VALUES (
'un_nom',
(
SELECT COUNT (id)+1
FROM test
WHERE nom = 'un_nom'
)
)

Voilà donc une solution qui marche, cependant, elle demande d'avoir connaissance de cette spécificité pour créer les requêtes d'insertion au niveau applicatif.

Ce qui au final ne me convient pas. Je vais donc plutôt m'orienter vers une solution basée sur les triggers comme le propose sparky.

...A moins qu'un complément d'info ou d'autre idées apparaissent :)

Merci de vos réponses si rapides !

++


Attention danger !

Jean-Paul Argudo/ = 21 Mars, 2006 - 12:22

Attention danger !

Les solutions qui vous ont été présentées sont correctes au niveau syntaxique. On aurait pu aussi définir une fonction en valeur par défaut, du coup votre "compteur" se serait mis à jour tout seul, sans écriture SQL.

Par contre, elles ne sont pas valides au niveau transactionnel.

Imaginez une transaction T1 qui démarre (BEGIN) et qui a son activité, entre le temps t0 et t10... différents ordres SQL passent...

La transaction T2 qui démarre à t2 fait un INSERT sur votre table avec auto-incrément. L'insert est { Luc, 3 }. Et la transaction T2 continue dans le temps, SANS COMMIT.

A t4, la transaction T1 fait un insert avec Luc à son tour... Comme cette transaction est dans son contexte, les données qui lui sont accessibles sont celles qu'elle avait au moment de son démarrage. Cette transaction essaie donc insérer { Luc, 3 }.

Vous allez donc vous retrouver dans une situation qui ne vous plaira pas: la transaction T1 est bloquée, en attente de COMMIT dans la transaction T2. Sur commit de T2, vous aurez une erreur parceque vous essayez d'insérer un doublon dans la table (pour peu que vous ayez une contrainte d'unicité (primary key) bien définie)...

C'est tout à fait comparable au problème des séquences PostgreSQL: c'est pour cela que les séquences PostgreSQL sont les seuls objets INDEPENDANTS des transactions....

C'est à dire que c'est le 1er qui réserve la valeur suivante de la séquence qui la prends. Si elle n'est pas utilisée, peu importe. Cette valeur ne peut être "prise" qu'une fois (système de ticket).

En conclusion, je pense que votre schéma de données est à revoir. Votre problématique n'as pas de solution avec { id, autoincrément }.

Je vous suggère d'avoir en clé primaire in { id } tout seul qui serait issu d'une séquence. Vous pouvez alors avoir un champs de type timestamp (avec un DEFAULT CURRENT_TIMESTAMP) pour "tracer" les inserts.. Il vous suffira alors d'une requête simple pour avoir les valeurs (dans notre exemple "Luc") insérées dans l'ordre et/ou les compter.

Je vous invite à parcourir le chapitre Contrôle d'accès simultané de la documentation de PostgreSQL pour une étude approfondie de votre problématique.

Cordialement,

--
Jean-Paul ARGUDO
www.dalibo.com


Bonjour, Je sentais bien q

ioguix/ = 21 Mars, 2006 - 15:59

Bonjour,

Je sentais bien que ma solution n'était pas la meilleure, mais j'avoue avoir un peu de mal à concillier la modélisation et l'optimisation dans certains cas...

Cette problèmatique transactionnelle m'avait effectivement échappée.

Merci beaucoup d'avoir pris le temps pour ces explications, précisions, informations et liens !

Cordialement,


c'est pour ça que je t'avais

sparky/ = 22 Mars, 2006 - 15:46

c'est pour ça que je t'avais conseillé un trigger : pour récupérer la séquence suivante puis insérer. Ou la créer si elle n'existe pas

exemple :
insert into (sam)

trigger before insert

si sequence sam n'existe pas, créer séquence sam,
prendre la nextval de la séquence et insérer ;)


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