IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PostgreSQL Discussion :

comment créer une nouvelle table à partir d'une déjà existante?


Sujet :

PostgreSQL

  1. #1
    Membre à l'essai
    Inscrit en
    Septembre 2006
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 25
    Points : 11
    Points
    11
    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.

  2. #2
    Membre émérite
    Avatar de hpalpha
    Inscrit en
    Mars 2002
    Messages
    769
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 769
    Points : 2 545
    Points
    2 545
    Par défaut
    Bonjour,

    tu peux essayer une fonction comme ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM transform_table()
    Il y a surrement plus optimisé mais je pense que deja ca te permettra d'avancer.
    Delphi 2009 - ZeosLib - DevExpress - TMS - PgDAC
    PostgreSQL 8.4 sous Debian
    Sites : http://postgresql.developpez.com http://dgriessinger.developpez.com

  3. #3
    Membre à l'essai
    Inscrit en
    Septembre 2006
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Merci, merci, merci.

    J'essaie et je te tiens informé!
    Bon week-end!

  4. #4
    Membre à l'essai
    Inscrit en
    Septembre 2006
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    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

  5. #5
    Membre émérite
    Avatar de hpalpha
    Inscrit en
    Mars 2002
    Messages
    769
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 769
    Points : 2 545
    Points
    2 545
    Par défaut
    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
    Delphi 2009 - ZeosLib - DevExpress - TMS - PgDAC
    PostgreSQL 8.4 sous Debian
    Sites : http://postgresql.developpez.com http://dgriessinger.developpez.com

  6. #6
    Membre à l'essai
    Inscrit en
    Septembre 2006
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    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?

  7. #7
    Membre à l'essai
    Inscrit en
    Septembre 2006
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    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?

  8. #8
    Membre émérite
    Avatar de hpalpha
    Inscrit en
    Mars 2002
    Messages
    769
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 769
    Points : 2 545
    Points
    2 545
    Par défaut
    Identé, c'est mettre en forme, decaler les block par des tab ou espaces :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    Delphi 2009 - ZeosLib - DevExpress - TMS - PgDAC
    PostgreSQL 8.4 sous Debian
    Sites : http://postgresql.developpez.com http://dgriessinger.developpez.com

  9. #9
    Membre à l'essai
    Inscrit en
    Septembre 2006
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    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?


  10. #10
    Membre à l'essai
    Inscrit en
    Septembre 2006
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    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?

  11. #11
    Membre émérite
    Avatar de hpalpha
    Inscrit en
    Mars 2002
    Messages
    769
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 769
    Points : 2 545
    Points
    2 545
    Par défaut
    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.
    Delphi 2009 - ZeosLib - DevExpress - TMS - PgDAC
    PostgreSQL 8.4 sous Debian
    Sites : http://postgresql.developpez.com http://dgriessinger.developpez.com

  12. #12
    Membre à l'essai
    Inscrit en
    Septembre 2006
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Ok tout est fait. Maintenant j'ai une erreur dans ma compilation. Voici le code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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?

  13. #13
    Membre émérite
    Avatar de hpalpha
    Inscrit en
    Mars 2002
    Messages
    769
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 769
    Points : 2 545
    Points
    2 545
    Par défaut
    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.
    Delphi 2009 - ZeosLib - DevExpress - TMS - PgDAC
    PostgreSQL 8.4 sous Debian
    Sites : http://postgresql.developpez.com http://dgriessinger.developpez.com

  14. #14
    Membre à l'essai
    Inscrit en
    Septembre 2006
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 );

  15. #15
    Membre à l'essai
    Inscrit en
    Septembre 2006
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    je me suis rendu compte que j'avais oublié SETOF dans le RETURNS de la fonction. Mais jusque la toujours la meme erreur!

  16. #16
    Membre à l'essai
    Inscrit en
    Septembre 2006
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    quelqu'un peut-il m'aider, je ne trouve tjrs pas l'erreur?

  17. #17
    Membre à l'essai
    Inscrit en
    Septembre 2006
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Voici la solution à mon problème:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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';

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [AC-2007] création d'une nouvelle table à partir d'une ancienne.
    Par sanzo-iko dans le forum Access
    Réponses: 2
    Dernier message: 16/06/2010, 14h02
  2. Réponses: 1
    Dernier message: 02/10/2009, 13h42
  3. Réponses: 3
    Dernier message: 30/09/2009, 14h15
  4. Réponses: 5
    Dernier message: 09/09/2007, 16h40
  5. Réponses: 4
    Dernier message: 11/10/2006, 09h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo