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 20/09/2006, 14h15   #1
Invité régulier
 
Inscription : septembre 2006
Messages : 25
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 25
Points : 6
Points : 6
Par défaut comment créer une nouvelle table à partir d'une déjà existante?

Salut,
j'aimerai créer une nouvelle table à partir d'une table déjà existante. La table existante a cette forme:

tel_id | tel_home | tel_mobile | friends_id
--------------------------------------------------------------------------------
0000 | 1001 | 0601 | 100
0001 | 1002 | 0602 | 100
0002 | 1003 | 0603 | 200
0003 | 1004 | 0604 | 200
0004 | 1005 | 0605 | 300
0005 | 1006 | 0606 | 400
0006 | 1007 | 0607 | 400
0007 | 1008 | 0608 | 400

friends_id est une clé secondaire (en principe ca n'a pas d'importance).

la nouvelle table devra ressembler à ceci:

tel_id |tel_home1 |tel_mobile1 |tel_home2 |tel_mobile2 | friends_id
---------------------------------------------------------------------------------------
0000 |1001 |0601 |1002 |0602 |100
0001 |1003 |0603 |1004 |0604 |200
0002 |1005 |0605 | | |300
0003 |1006 |0606 |1007 |0607 |400

c'est-à dire par ligne juste une seule fois friends_id et pour plus de 3 numéros(par ex. friends_id = 400), le troisième n° sera tout simplement abandonné.

comment est-ce ke je pourrais faire cela avec PSQL?

Merci de votre aide.
odi_9 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/09/2006, 08h01   #2
Membre émérite
 
Avatar de hpalpha
 
Inscription : mars 2002
Messages : 770
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 770
Points : 833
Points : 833
Bonjour,

tu peux essayer une fonction comme ca :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CREATE TYPE typeperso AS ( tel_id varchar, tel_home1 varchar, tel_mobile1 varchar, tel_home2 varchar, tel_mobile2 varchar, friends_id varchar);
 
CREATE OR REPLACE FUNCTION transform_table() RETURNS SETOF typeperso AS
$BODY$
DECLARE
 rec record;
 o typeperso;
BEGIN
 FOR rec IN SELECT friends_id FROM matable GROUP BY friends_id ORDER BY friends_id
 LOOP
   o.friends_id:=rec.friends_id;
   SELECT INTO o.tel_id,o.tel_home1,o.tel_mobile1 tel_id,tel_home,tel_mobile FROM matable WHERE friends_id = rec.friends_id ORDER BY tel_id LIMIT 1 OFFSET 0;
   SELECT INTO o.tel_home2,o.tel_mobile2 tel_home,tel_mobile FROM matable WHERE friends_id = rec.friends_id ORDER BY tel_id LIMIT 1 OFFSET 1;
   RETURN NEXT o;
 END LOOP ;
 RETURN ;
end;
$BODY$
LANGUAGE 'plpgsql' ;
pour l'utiliser

Code :
SELECT * FROM transform_table()
Il y a surrement plus optimisé mais je pense que deja ca te permettra d'avancer.
hpalpha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/09/2006, 11h55   #3
Invité régulier
 
Inscription : septembre 2006
Messages : 25
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 25
Points : 6
Points : 6
Merci, merci, merci.

J'essaie et je te tiens informé!
Bon week-end!
odi_9 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/09/2006, 21h33   #4
Invité régulier
 
Inscription : septembre 2006
Messages : 25
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 25
Points : 6
Points : 6
Salut,

pour m'assurer avoir compris l'exemple proposé plus haut et après avoir longuement lu le tutoriel, j'ai essayé pour résoudre mon probleme le code suivant que j'exécute dans le shell. Ma question est de savoir pourkoi est-ce ke je recois l'erreur qui suit le code? Et est-ce ke les 'expression [index]' sont-ils bien utilisé dans la mesure où je voudrais vérifier une ligne et la suivante ?

CREATE OR REPLACE FUNCTION transform_table_address() RETURNS SETOF attribut_address_2 AS $BODY$

DECLARE
rec RECORD,
o attribut_address_2,
index INTEGER
BEGIN
SELECT rec.name1, rec.name2, rec.street, rec.zip, rec.zipcity, rec.country, rec.state FROM address

WHILE rec.company_id[index] = rec.company_id[index + 1] AND rec.street[index + 1] NOT NULL

LOOP RETURN NEXT O(rec.name1, rec.name2, rec.company_id, rec.street, rec.zip [index +1], rec.zipcity[index +1], rec.country[index+1], rec.state[index + 1])

IF rec.company_id[index] = rec.company_id [index +1+1] THEN NULL
END IF
END LOOP
RETURN
END
$BODY$ LANGUAGE 'plpgsql';
--voici l'erreur
ERROR: parser: parse error at or near "$" at character 90
odi_9 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/09/2006, 08h31   #5
Membre émérite
 
Avatar de hpalpha
 
Inscription : mars 2002
Messages : 770
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 770
Points : 833
Points : 833
Je pense qu'il y a beaucoup d'erreur dans ce code :

- il manque des points virgules a chaque fin d'instruction (déclaration des variables aussi)
- evite d'utiliser des mots clefs dans tes variables comme index
- un type record est une ligne pas une sorte de array, on ne peut donc pas acceder a l'enregistrement suivant avec un index
- rec.company_id[index] = rec.company_id[index + 1] AND rec.street[index + 1] NOT NULL ne retourne pas un boolean fait plutot rec.company_id[index] = rec.company_id[index + 1] AND rec.street[index + 1] IS NOT NULL
- essaye d'identer ta fonction, c'est plus facile pour debuger

en tout cas c'est un bel effort, continue comme ca, tu va voir meme si plpgsql est un language simple, ca va te faciliter la vie dans bien des situations
hpalpha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/09/2006, 09h40   #6
Invité régulier
 
Inscription : septembre 2006
Messages : 25
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 25
Points : 6
Points : 6
C'est motivant les encouragements du genre!

Quand j'entre le code dans le shell avec des points virgules, je recois des erreurs, mais en les enlevant elles disparaissent toutes jusqu'à celle cité plus haut.
J'ai aussi essayé le code que tu m'as proposé en le restructurant en fonction de de mes besoins, mais toujours la meme erreur.

Je continue en tout cas de chercher.

PS: c'est koi identer une fonction?
odi_9 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/09/2006, 10h44   #7
Invité régulier
 
Inscription : septembre 2006
Messages : 25
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 25
Points : 6
Points : 6
Citation:
Envoyé par odi_9
C'est motivant les encouragements du genre!

Quand j'entre le code dans le shell avec des points virgules, je recois des erreurs, mais en les enlevant elles disparaissent toutes jusqu'à celle cité plus haut.
J'ai aussi essayé le code que tu m'as proposé en le restructurant en fonction de de mes besoins, mais toujours la meme erreur.

Je continue en tout cas de chercher.

PS: c'est koi identer une fonction?
odi_9 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/09/2006, 10h58   #8
Membre émérite
 
Avatar de hpalpha
 
Inscription : mars 2002
Messages : 770
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 770
Points : 833
Points : 833
Identé, c'est mettre en forme, decaler les block par des tab ou espaces :


Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CREATE OR REPLACE FUNCTION transform_table_address() RETURNS SETOF attribut_address_2 AS $BODY$
 
DECLARE
rec RECORD,
o attribut_address_2,
INDEX INTEGER
BEGIN
SELECT rec.name1, rec.name2, rec.street, rec.zip, rec.zipcity, rec.country, rec.state FROM address
 
WHILE rec.company_id[INDEX] = rec.company_id[INDEX + 1] AND rec.street[INDEX + 1] NOT NULL
 
LOOP RETURN NEXT O(rec.name1, rec.name2, rec.company_id, rec.street, rec.zip [INDEX +1], rec.zipcity[INDEX +1], rec.country[INDEX+1], rec.state[INDEX + 1])
 
IF rec.company_id[INDEX] = rec.company_id [INDEX +1+1] THEN NULL
END IF
END LOOP
RETURN
END
$BODY$ LANGUAGE 'plpgsql';
devient

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
CREATE OR REPLACE FUNCTION transform_table_address() RETURNS SETOF attribut_address_2 AS $BODY$
DECLARE
 rec RECORD,
 o attribut_address_2,
 INDEX INTEGER
BEGIN
   SELECT rec.name1, rec.name2, rec.street, rec.zip, rec.zipcity, rec.country,  rec.state FROM address
 
   WHILE rec.company_id[INDEX] = rec.company_id[INDEX + 1] AND rec.street[INDEX + 1] NOT NULL LOOP
       RETURN NEXT O(rec.name1, rec.name2, rec.company_id, rec.street, rec.zip [INDEX +1], rec.zipcity[INDEX +1], rec.country[INDEX+1], rec.state[INDEX + 1])
       IF rec.company_id[INDEX] = rec.company_id [INDEX +1+1] THEN
         NULL
       END IF
   END LOOP
   RETURN
END
$BODY$ LANGUAGE 'plpgsql';
pour les problemes de points virgules, je vois pas, a pars peut etre que dans psql le point virgule indique que la commande est finie d etre saisie et elle doit etre interprété, mais il detecte lorsque l'on creer une fonction, donc normalement ca devrait passer, essaye avec un editeur evolué comme pgadmin.

Si tu peux fait un screenshot
hpalpha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/09/2006, 10h59   #9
Invité régulier
 
Inscription : septembre 2006
Messages : 25
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 25
Points : 6
Points : 6
Ok du nouveau,

Alors l'erreur que j'obtenais jusqu'ici venait de la définition de ma fonction.
Au lieu de

CREATE OR REPLACE FUNCTION nom_de_la_fonction () RETURNS type AS $BODY$
DECLARE
déclaration
BEGIN
...
END
$BODY$

LANGUAGE 'plpgsql'

ca aurait du etre

CREATE OR REPLACE FUNCTION nom_de_la_fonction () RETURNS type AS ' --ici
DECLARE
déclaration
BEGIN
...
END' --ici
LANGUAGE 'plpgsql'

résultat: ERROR: language "plpqsql" doest not exist

Maintenant je dois déclarer le language plpgsql dans ma base.

Mais en utilisant CREATE LANGUAGE 'plpgsql'; ou avec la fonction createlang nomlang ; je recois comme erreur : ERROR: parser: parse error at or near ";"

que faire?

odi_9 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/09/2006, 11h22   #10
Invité régulier
 
Inscription : septembre 2006
Messages : 25
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 25
Points : 6
Points : 6
Je crois savoir pourqoui est-ce que j'ai tant de problème. C'est surement à cause de ma version de PostgreSQL. Version 7.3.10. Comment est-ce que je fais un update?
odi_9 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/09/2006, 11h23   #11
Membre émérite
 
Avatar de hpalpha
 
Inscription : mars 2002
Messages : 770
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 770
Points : 833
Points : 833
pour installer le plpgsql, tu te met en shell comme si tu lancais psql, mais tu lance une autre commande : createlang
cette commande est bien un programme et pas une commande SQL a faire sous psql.
hpalpha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/09/2006, 15h44   #12
Invité régulier
 
Inscription : septembre 2006
Messages : 25
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 25
Points : 6
Points : 6
Ok tout est fait. Maintenant j'ai une erreur dans ma compilation. Voici le code:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
CREATE OR REPLACE FUNCTION transform_table_address () RETURNS transform_address_attribut AS /*$BODY$*/'
DECLARE
rec RECORD;
O transform_address_attribut;
 
BEGIN
FOR rec IN SELECT company_id FROM address GROUP BY company_id
 
LOOP
 
o.company_id := rec.company_id;
SELECT INTO o.company_id, o.name1, o.name2, o.street, o.zip, o.zipcity, o.country, o.state, company_id, name1, name2, street, zip, zipcity, country, state FROM address GROUP BY company_id LIMIT 1;
SELECT INTO o.street2, o.zip2, o.zipcity2, o.country2, o.state2 street, zip, zipcity, country, state FROM address WHERE company_id = rec.company_id GROUP BY company_id LIMIT 1;
	IF (SELECT company_id FROM address WHERE company_id = rec.company_id IS NOT NULL )
		THEN
			EXIT;
	END IF;
    RETURN NEXT O;
END LOOP;	 
    RETURN;
END;
/*$BODY$*/'
LANGUAGE 'plpgsql';
ERROR: Incorrect argument to RETURN NEXT at or near "O"

Qu'est-ce ke ca peut bien etre?
odi_9 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/09/2006, 16h00   #13
Membre émérite
 
Avatar de hpalpha
 
Inscription : mars 2002
Messages : 770
Détails du profil
Informations forums :
Inscription : mars 2002
Messages : 770
Points : 833
Points : 833
Dans un SELECT INTO var1, var2 val1,val2 FROM matable
il n'y a par de virgule entre la derniere variable et la premiere valeur

ensuite tu ne peut pas ecrire
IF (SELECT company_id FROM address WHERE company_id = rec.company_id IS NOT NULL )
THEN
EXIT;
END IF;


le IF ne peut pas evaluer une requete, il faut que tu la traite avant.

en tout cas c'est pas mal, je ne regarde pas le coté algo mais seulement la syntaxe.
hpalpha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/09/2006, 16h49   #14
Invité régulier
 
Inscription : septembre 2006
Messages : 25
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 25
Points : 6
Points : 6
Après avoir corrigé le code, le problème reste le meme. Il a un problème avec le type que j'attribut à RETURN NEXT o

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
CREATE OR REPLACE FUNCTION transform_table_address () RETURNS transform_address_attribut AS /*$BODY$*/'
DECLARE
rec RECORD;
o transform_address_attribut;
 
BEGIN
FOR rec IN SELECT company_id FROM address GROUP BY company_id
 
LOOP
o.company_id := rec.company_id;
SELECT INTO o.company_id, o.name1, o.name2, o.street, o.zip, o.zipcity, o.country, o.state company_id, name1, name2, street, zip, zipcity, country, state FROM address ORDER BY company_id LIMIT 1;
SELECT INTO o.street2, o.zip2, o.zipcity2, o.country2, o.state2 street, zip, zipcity, country, state FROM address WHERE company_id = rec.company_id ODER BY company_id LIMIT 1;
	 SELECT company_id FROM address WHERE company_id = rec.company_id LIMIT 1;
	 IF (rec.company_id = company_id)
		THEN
			EXIT;
	END IF;
    RETURN NEXT o;
END LOOP;	 
    RETURN;
END;
/*$BODY$*/'
LANGUAGE 'plpgsql';
Voici comment j'ai défini le type transform_address_attribut de o

Code :
1
2
3
CREATE TYPE transform_address_attribut AS ( company_id VARCHAR, name1 
VARCHAR, name2 VARCHAR, street VARCHAR, zip VARCHAR, zipcity 
VARCHAR, country VARCHAR, state VARCHAR, street2 VARCHAR, zip2 VARCHAR, zipcity2 VARCHAR, country2 VARCHAR, state VARCHAR );
odi_9 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/09/2006, 19h43   #15
Invité régulier
 
Inscription : septembre 2006
Messages : 25
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 25
Points : 6
Points : 6
je me suis rendu compte que j'avais oublié SETOF dans le RETURNS de la fonction. Mais jusque la toujours la meme erreur!
odi_9 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/10/2006, 17h52   #16
Invité régulier
 
Inscription : septembre 2006
Messages : 25
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 25
Points : 6
Points : 6
quelqu'un peut-il m'aider, je ne trouve tjrs pas l'erreur?
odi_9 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/10/2006, 10h12   #17
Invité régulier
 
Inscription : septembre 2006
Messages : 25
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 25
Points : 6
Points : 6
Voici la solution à mon problème:

Code :
1
2
3
4
CREATE TYPE transform_address_attribut AS ( company_id VARCHAR, name1 
VARCHAR, name2 VARCHAR, street VARCHAR, zip VARCHAR, zipcity VARCHAR, 
country VARCHAR, state VARCHAR, street2 VARCHAR, zip2 VARCHAR, zipcity2 
VARCHAR, country2 VARCHAR, state2 VARCHAR );
Code :
1
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
32
CREATE OR REPLACE FUNCTION transform_table_address () RETURNS  SETOF 
transform_address_attribut AS /*$BODY$*/'

DECLARE
 rec RECORD;
 o transform_address_attribut%ROWTYPE; -- L'erreur était à ce niveau
 help address%ROWTYPE;                      

BEGIN
 FOR rec IN SELECT company_id FROM address GROUP BY company_id ORDER BY 
company_id asc
 LOOP  
   o.company_id := rec.company_id;
   SELECT INTO o.company_id, o.name1, o.name2, o.street, o.zip, 
o.zipcity, o.country,
   o.state   company_id, name1, name2, street, zip, zipcity, country, 
state FROM address         WHERE company_id = rec.company_id AND 
address.name1 IS NOT NULL ORDER BY company_id asc LIMIT 1; 

  SELECT * INTO help from address WHERE company_id = rec.company_id AND 
address.street IS NOT NULL limit 1; 
  IF ( help.street IS NOT NULL and help.street <> o.street)  THEN
   SELECT INTO o.street2, o.zip2, o.zipcity2, o.country2, o.state2  
street, zip, zipcity,country, state FROM address WHERE    company_id = 
rec.company_id AND street IS NOT NULL ORDER BY company_id asc LIMIT 1; 
  END IF;
   RETURN NEXT o;   
 END LOOP;
 RETURN;
END;
/*$BODY$*/'
LANGUAGE 'plpgsql';
odi_9 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 08h44.


 
 
 
 
Partenaires

Hébergement Web