Précédent   Forum des professionnels en informatique > Bases de données > PostgreSQL
PostgreSQL Forum PostgreSQL. Avant de poster -> F.A.Q PostGreSQL Tutoriels PostGreSQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 03/09/2007, 10h36   #1
Candidat au titre de Membre du Club
 
Inscription : novembre 2006
Messages : 72
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 72
Points : 11
Points : 11
Par défaut Fusion avec clefs

(Postgresql 8.2)
Voila : j'ai deux tables A et B. A contient une clef primaire (id) et B une clef etrangere (id). Il y a au moins 1000 lignes dans B pour chaque id.

Il y a 2 lignes dans A (=> 2000 lignes dans B)

J'aimerais fusionner les lignes de B avec un seul id de A:
Shématiquement, on aurait :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
A                   B
--                 -------
1                   1
2                   ..
                    1
                    2
                    ..
                    2
===========================
Pour donner :
 
A                   B
--                 -------
3                   3
==                 ..
                    3
==============================
Je cherche une autre solution que de changer directement la table B. (Il n'y a pas qu'une seule table B et il peut y en avoir de nouvelles, ce qui m'obligerait à transformer ma requête SQL à chaque fois)
Je pensais par exemple à forcer un update sur une ligne de A (id 1 => 2) ce qui changerait les id dans B, puis de supprimer la ligne de A (mais ça risque de supprimer aussi les lignes de B vu que cette bidouille ne devrait pas être prevue par postgres)

Des idées?
ledjlale est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/09/2007, 15h32   #2
Membre habitué
 
Inscription : août 2007
Messages : 128
Détails du profil
Informations forums :
Inscription : août 2007
Messages : 128
Points : 146
Points : 146
Je ne suis pas sûr d'avoir tout compris mais si je suis ce que tu dis je ferais ceci

Code :
1
2
3
4
5
BEGIN;
INSERT INTO A (id) VALUES (3);
UPDATE B SET id=3;
DELETE FROM A WHERE id<>3;
COMMIT;
gleu_ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/09/2007, 16h45   #3
Candidat au titre de Membre du Club
 
Inscription : novembre 2006
Messages : 72
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 72
Points : 11
Points : 11
Oui et non

Ce que tu proposes est ce que je ne voulais pas faire
Citation:
Je cherche une autre solution que de changer directement la table B.
Tu fais un UPDATE B SET id=3;
Sans chipoter sur les clauses WHERE de l'update :
Tu agis directement dans B. Si il y a 10 tables "B", tu serais obligé d'avoir 10 fois ton UPDATE. Si je rajoute encore une table Bn, il faudra que je pense à changer la fonction et rajouter un update dedans. C'est ce que je veux éviter de faire.
ledjlale est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/09/2007, 23h00   #4
Membre habitué
 
Inscription : août 2007
Messages : 128
Détails du profil
Informations forums :
Inscription : août 2007
Messages : 128
Points : 146
Points : 146
Alors explique mieux ton problème, sinon je serais dans l'impossibilité de t'aider
gleu_ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/09/2007, 14h04   #5
Candidat au titre de Membre du Club
 
Inscription : novembre 2006
Messages : 72
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 72
Points : 11
Points : 11
C'est faire en gros ce que tu as proposé, sans toucher explicitement à la table B ou alors de façon générique qui éviterait d'avoir à changer la fonction à chaque fois qu'on rajoute/enleve une table B.

L'exemple qui me donne le résultat mais que je ne veux pas utiliser serait le suivant :
Code :
1
2
3
 
UPDATE B SET id = 2 WHERE id = 1;
DELETE FROM A WHERE id = 1;
=> je fusionne les lignes de B associés à A par l'id 1 avec les lignes de B associés à A par l'id 2.

Pour le shémas du premier post, ce serait plutot :
Code :
1
2
3
4
 
UPDATE A SET id = 3 WHERE id = 2;
UPDATE B SET id = 3 WHERE id = 1;
DELETE FROM A WHERE id = 1;
Si tu ne vois pas encore pourquoi je ne veux pas utiliser cette solution, imagine que je veuille rajouter une table B2 ayant les même caracteristique que B. Il faudrait que je change la fonction :
Code :
1
2
3
4
5
 
UPDATE A SET id = 3 WHERE id = 2;
UPDATE B SET id = 3 WHERE id = 1;
UPDATE B2 SET id = 3 WHERE id = 1;
DELETE FROM A WHERE id = 1;
Ce n'est pas grand chose à faire que de rajouter un update par-ci, un update par-là. Mais ça oblige l'adminitrateur à savoir quelles fonctions changer si il veut rajouter/supprimer une table. (Surtout quand il y a une dizaine de fontions)
ledjlale est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/09/2007, 14h25   #6
Invité régulier
 
Inscription : août 2007
Messages : 10
Détails du profil
Informations forums :
Inscription : août 2007
Messages : 10
Points : 8
Points : 8
Si sur B.id il y a la contrainte FOREIGN KEY avec ON UPDATE CASCADE et ON DELETE NO ACTION, tu peux updater la ligne dans A pour modifier d'un coup toutes les lignes de B, puis supprimer la ligne de A (puisqu'il y a un ON DELETE NO ACTION), la vérification de la contrainte de B sur A aura lieu a la fin de la transaction, donc peu importe quelles lignes sont supprimées dans A tant qu'a la fin pour tout id dans B il y en a un dans A
Makkhdyn est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/09/2007, 15h06   #7
Candidat au titre de Membre du Club
 
Inscription : novembre 2006
Messages : 72
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 72
Points : 11
Points : 11
Citation:
la vérification de la contrainte de B sur A aura lieu a la fin de la transaction,
mmm interessant

Si il y a un DELETE NO ACTION : ça veut dire qu'il y a un probleme si je fais un "DELETE FROM A WHERE id=7;" : ça ne nettoyera pas B. Et pire, ça n'effacera pas la ligne dans A parcequ'il n'y aurait plus de lien A-B

Ho, mais peut etre que je peux changer pendant la transaction les contraintes sur la clef étrangère pour mettre en NO ACTION, et remettre ensuite CASCADE juste avant la fin de la transaction. Cette solution est-elle viable (perf. ...)?
ledjlale est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/09/2007, 17h33   #8
Membre habitué
 
Inscription : août 2007
Messages : 128
Détails du profil
Informations forums :
Inscription : août 2007
Messages : 128
Points : 146
Points : 146
La vérification de la contrainte n'a lieu à la fin de la transaction que si les contraintes de la table sont déclarées comme étant déferrable. Voir pour cela la page man de SET CONSTRAINTS (http://www.postgresql.org/docs/8.2/i...nstraints.html).
gleu_ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/09/2007, 18h23   #9
Invité régulier
 
Inscription : août 2007
Messages : 10
Détails du profil
Informations forums :
Inscription : août 2007
Messages : 10
Points : 8
Points : 8
Citation:
Envoyé par gleu_ Voir le message
La vérification de la contrainte n'a lieu à la fin de la transaction que si les contraintes de la table sont déclarées comme étant déferrable. Voir pour cela la page man de SET CONSTRAINTS (http://www.postgresql.org/docs/8.2/i...nstraints.html).
Je ne suis pas sûr que ça soit le cas avec le ON DELETE NO ACTION, j'ai vu quelques exemples dans la doc, aucun ne parlait de rendre en plus la contrainte déférrable
Makkhdyn est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 00h15.


 
 
 
 
Partenaires

Hébergement Web