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

Interfaces de programmation Oracle Discussion :

[PRO*C] Allocation dynamique d'un tableau de VARCHAR


Sujet :

Interfaces de programmation Oracle

  1. #1
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 19
    Points : 12
    Points
    12
    Par défaut [PRO*C] Allocation dynamique d'un tableau de VARCHAR
    Bonjour,

    Je souhaite récupérer des données de la base avant d'en insérer d'autres. Comme je manipule de très grosses masses de données, je dois procéder par blocs dont la taille n'est pas fixée à la compilation.
    Je n'ai pas de problème avec les types scalaires (int...) mais pour VARCHAR, je dois dire que je bloque.

    Voici du code qui ne passe pas mais qui donne, je pense une bonne idée de ce que je veux faire :
    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
    33
    34
    35
    36
    37
    38
    39
    int i; /* Compteur */
    EXEC SQL BEGIN DECLARE SECTION;
    	int bloc; /* Taille d'un bloc */
    	int* tNum; /*Numeros des gens */
    	VARCHAR** tNom; /* Noms des gens */
    EXEC SQL END DECLARE SECTION;
     
    bloc = 100; /* Recupere dynamiquement (parametrable) */
     
    tNum = (int*) malloc(bloc * sizeof(*tNum));
     
    /* Le probleme est juste la... */
    tNom = (VARCHAR**) malloc(bloc * sizeof(*tNom));
    for(i = 0; i < bloc; i++) {
    	tNom[i] = (VARCHAR*) malloc(20 * sizeof(**tNom)); /* 20 : Taille d'un nom */
    }
     
    EXEC SQL DECLARE c_gens CURSOR FOR SELECT num, nom FROM gens;
    /* Gestion des erreurs */
     
    EXEC SQL OPEN c_gens;
    /* Gestion des erreurs */
     
    EXEC SQL FOR :bloc FETCH c_gens INTO :tNum, :tNom;
    /* Gestion des erreurs */
    while(/* encore des lignes, je sais faire mais le probleme n'est pas la */) {
    	/* Traitements sur tNum et tNom */
     
    	EXEC SQL FOR :bloc INSERT INTO client(num, nom) VALUES (:tNum, :tNom);
     
    	EXEC SQL FOR :bloc FETCH c_gens INTO :tNum, :tNom;
    	/* Gestion des erreurs */
    }
     
    free(tNum);
    for(i = 0; i < bloc; i++) {
    	free(tNom[i]);
    }
    free(tNom);
    En fait le problème vient du fait que VARCHAR n'est pas simplement un tableau de caractères comme en C classique, le précompilateur Pro*C créé une structure.

    La question est : peut-on faire une allocation dynamique d'un tableau de VARCHAR pour l'utilisation de Host Array ?

    Merci par avance !

    Edit : Pro*C/C++: Release 9.2.0.4.0

  2. #2
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 19
    Points : 12
    Points
    12
    Par défaut Bon forum ?
    Mon message est-il sur le bon forum ou aurait-il plus sa place dans la section C ?
    J'ai pas mal hésité en postant...

  3. #3
    Expert éminent sénior
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Points : 11 862
    Points
    11 862
    Par défaut
    Il est bien sur le bon forum, cependant les programmeurs Pro*C ne sont pas nombreux...
    N'avez-vous trouvé aucun example dans la doc Pro*C ?
    la structure décrivant les Varchar2 y est très bien expliquée, il me semble.
    Rédacteur Oracle (Oracle ACE)
    Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
    Je ne réponds pas aux questions techniques par MP
    Blogs: Forms-PL/SQL-J2EE - Forms Java Beans

  4. #4
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 19
    Points : 12
    Points
    12
    Par défaut
    Je comprends qu'il n'y aie pas beaucoup de développeurs Pro*C, moi-même, si j'avais le choix...
    Les seuls exemples que j'ai pu trouver portent sur des tableaux fixes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #define BLOC 100
    VARCHAR tNom[BLOC][9 * NBXXXX];
    J'ai lu une page sur l'allocation dynamique des tableaux de VARCHAR mais je n'ai pas été convaincu par la portabilité de la méthode (lors de la compilation sous différents environnements).

    Je pense que je vais essayer de me passer de l'allocation dynamique, tant pis.

    Merci quand même.

    PS : Pour la "beauté de l'art", si quelqu'un trouve un début de solution, je suis tout de même interressé

  5. #5
    Expert éminent sénior
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Points : 11 862
    Points
    11 862
    Par défaut
    J'ai trouvé cceci dans la doc. Peut-être cela vous aidera t-il...

    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
     
    /*
    * The sqlvcp.pc program demonstrates how you can use the
    * sqlvcp() function to determine the actual size of a
    * VARCHAR struct. The size is then used as an offset to
    * increment a pointer that steps through an array of
    * VARCHARs.
    *
    * This program also demonstrates the use of the sqlgls()
    * function, to get the text of the last SQL statement executed.
    * sqlgls() is described in the "Error Handling" chapter of
    * The Programmer’s Guide to the Oracle Pro*C/C++ Precompiler.
    */
    #include <stdio.h>
    #include <sqlca.h>
    #include <sqlcpr.h>
    /* Fake a VARCHAR pointer type. */
    struct my_vc_ptr
    {
    unsigned short len;
    unsigned char arr[32767];
    };
    /* Define a type for the VARCHAR pointer */
    typedef struct my_vc_ptr my_vc_ptr;
    my_vc_ptr *vc_ptr;
    EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR *names;
    int limit; /* for use in FETCH FOR clause */
    char *username = "scott/tiger";
    EXEC SQL END DECLARE SECTION;
    void sql_error();
    extern void sqlvcp(), sqlgls();
    main()
    {
    See Also: Chapter 9, "Handling Runtime Errors"
    VARCHAR Variables
    Datatypes and Host Variables 4-27
    unsigned int vcplen, function_code, padlen, buflen;
    int i;
    char stmt_buf[120];
    EXEC SQL WHENEVER SQLERROR DO sql_error();
    EXEC SQL CONNECT :username;
    printf("\nConnected.\n");
    /* Find number of rows in table. */
    EXEC SQL SELECT COUNT(*) INTO :limit FROM emp;
    /* Declare a cursor for the FETCH statement. */
    EXEC SQL DECLARE emp_name_cursor CURSOR FOR
    SELECT ename FROM emp;
    EXEC SQL FOR :limit OPEN emp_name_cursor;
    /* Set the desired DATA length for the VARCHAR. */
    vcplen = 10;
    /* Use SQLVCP to help find the length to malloc. */
    sqlvcp(&vcplen, &padlen);
    printf("Actual array length of VARCHAR is %ld\n", padlen);
    /* Allocate the names buffer for names.
    Set the limit variable for the FOR clause. */
    names = (VARCHAR *) malloc((sizeof (short) +
    (int) padlen) * limit);
    if (names == 0)
    {
    printf("Memory allocation error.\n");
    exit(1);
    }
    /* Set the maximum lengths before the FETCH.
    * Note the "trick" to get an effective VARCHAR *.
    */
    for (vc_ptr = (my_vc_ptr *) names, i = 0; i < limit; i++)
    {
    vc_ptr->len = (short) padlen;
    vc_ptr = (my_vc_ptr *)((char *) vc_ptr +
    padlen + sizeof (short));
    }
    /* Execute the FETCH. */
    EXEC SQL FOR :limit FETCH emp_name_cursor INTO :names;
    VARCHAR Variables
    4-28 Pro*C/C++ Precompiler Programmer’s Guide
    /* Print the results. */
    printf("Employee names--\n");
    for (vc_ptr = (my_vc_ptr *) names, i = 0; i < limit; i++)
    {
    printf
    ("%.*s\t(%d)\n", vc_ptr->len, vc_ptr->arr, vc_ptr->len);
    vc_ptr = (my_vc_ptr *)((char *) vc_ptr +
    padlen + sizeof (short));
    }
    /* Get statistics about the most recent
    * SQL statement using SQLGLS. Note that
    * the most recent statement in this example
    * is not a FETCH, but rather "SELECT ENAME FROM EMP"
    * (the cursor).
    */
    buflen = (long) sizeof (stmt_buf);
    /* The returned value should be 1, indicating no error. */
    sqlgls(stmt_buf, &buflen, &function_code);
    if (buflen != 0)
    {
    /* Print out the SQL statement. */
    printf("The SQL statement was--\n%.*s\n", buflen, stmt_buf);
    /* Print the returned length. */
    printf("The statement length is %ld\n", buflen);
    /* Print the attributes. */
    printf("The function code is %ld\n", function_code);
    EXEC SQL COMMIT RELEASE;
    exit(0);
    }
    else
    {
    printf("The SQLGLS function returned an error.\n");
    EXEC SQL ROLLBACK RELEASE;
    exit(1);
    }
    }
    void
    sql_error()
    {
    char err_msg[512];
    int buf_len, msg_len;
    EXEC SQL WHENEVER SQLERROR CONTINUE;
    buf_len = sizeof (err_msg);
    sqlglm(err_msg, &buf_len, &msg_len);
    printf("%.*s\n", msg_len, err_msg);
    EXEC SQL ROLLBACK RELEASE;
    exit(1);
    }
    Rédacteur Oracle (Oracle ACE)
    Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
    Je ne réponds pas aux questions techniques par MP
    Blogs: Forms-PL/SQL-J2EE - Forms Java Beans

  6. #6
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 19
    Points : 12
    Points
    12
    Par défaut
    Merci bien !
    C'est exactement le genre de chose à laquelle je pensais.

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

Discussions similaires

  1. Réponses: 24
    Dernier message: 26/04/2007, 15h20
  2. [debutant] allocation dynamique d'un tableau.
    Par méphistopheles dans le forum Débuter
    Réponses: 3
    Dernier message: 16/03/2007, 12h45
  3. Réponses: 2
    Dernier message: 05/03/2007, 18h37
  4. Réponses: 67
    Dernier message: 13/02/2007, 18h08
  5. Réponses: 13
    Dernier message: 01/10/2006, 00h25

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