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

C++ Discussion :

Insertion de données avec SQLITE3


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2019
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Guinée

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2019
    Messages : 9
    Par défaut Insertion de données avec SQLITE3
    Bonjour,

    Est-ce que c'est possible d'insérer des données avec sqlite3 en utilisant des variables plutôt que de passer directement le texte dans la requête.
    Si oui, comment ?
    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
    #include <iostream>
    #include <string>
    #include <cstdio>
    #include "../../../../Sqlite/sqlite3.h"
     
    using namespace std;
     
    static int callback(void* data, int argc, char** argv, char** azColName)
    {
        fprintf(stderr, "%s: ", (const char*)data);
     
        for (int i = 0; i < argc; i++) {
            printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
        }
     
        printf("\n");
        return 0;
    }
     
    int main(int argc, char** argv)
    {
        sqlite3* DB;
        char* messaggeError;
        int exit = sqlite3_open("C:/Users/Dell/Desktop/sqlite_project/mabase.db", &DB);
        string query = "SELECT * FROM PERSON;";
     
        cout << "STATE OF TABLE BEFORE INSERT" << endl;
     
        sqlite3_exec(DB, query.c_str(), callback, NULL, NULL);
     
        string sql("INSERT INTO PERSON VALUES(1, 'jul', 'GATES', 30, 'PALO ALTO', 1000.0);"
                "INSERT INTO PERSON VALUES(2, 'BILL', 'ALLEN', 20, 'SEATTLE', 300.22);"
                "INSERT INTO PERSON VALUES(3, 'PAUL', 'JOBS', 24, 'SEATTLE', 9900.0);");
     
        exit = sqlite3_exec(DB, sql.c_str(), NULL, 0, &messaggeError);
        if (exit != SQLITE_OK) {
            cerr << "Error Insert" << endl;
            sqlite3_free(messaggeError);
        }
        else
            cout << "Records created Successfully!" << endl;
     
        cout << "STATE OF TABLE AFTER INSERT" << endl;
     
        sqlite3_exec(DB, query.c_str(), callback, NULL, NULL);
     
        sql = "DELETE FROM PERSON WHERE ID = 2;";
        exit = sqlite3_exec(DB, sql.c_str(), NULL, 0, &messaggeError);
        if (exit != SQLITE_OK) {
            cerr << "Error DELETE" << endl;
            sqlite3_free(messaggeError);
        }
        else
            cout << "Record deleted Successfully!" << endl;
     
        cout << "STATE OF TABLE AFTER DELETE OF ELEMENT" << endl;
        sqlite3_exec(DB, query.c_str(), callback, NULL, NULL);
     
        sqlite3_close(DB);
        return (0);
    }

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Les appels prennent des string. Si tu veux intégrer des variables, ça s'appelle formater sa chaîne de caractères au préalable.
    Les lib sql proposent généralement un système de prepared statement qui permet de faire ça de façon sécurisée.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2019
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Guinée

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2019
    Messages : 9
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Les appels prennent des string. Si tu veux intégrer des variables, ça s'appelle formater sa chaîne de caractères au préalable.
    Les lib sql proposent généralement un système de prepared statement qui permet de faire ça de façon sécurisée.
    Comment pourrais-je le faire ? Je ne trouve pas assez d'informations sur le net.
    Tu peux me guider un peu plus ?

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 637
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 637
    Par défaut
    Citation Envoyé par Dia390 Voir le message
    Comment pourrais-je le faire ? Je ne trouve pas assez d'informations sur le net.
    Tu peux me guider un peu plus ?
    C'est à se demander pourquoi il se décarcasse à te faire un long message qui reprend l'ensemble des informations dont tu as besoin, le koala...
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2019
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Guinée

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2019
    Messages : 9
    Par défaut
    J'ai implémenté ton algorithme mais ça marche pas. Le problème est que je ne suis qu'un débutant donc essaye de rendre les choses beaucoup plus clairs et limpides.

  6. #6
    Membre Expert Avatar de gabriel21
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2007
    Messages : 548
    Par défaut
    Citation Envoyé par koala01 Voir le message
    C'est à se demander pourquoi il se décarcasse à te faire un long message qui reprend l'ensemble des informations dont tu as besoin, le koala...
    J'ai appris plusieurs choses. Surtout que c'est une question que je comptais poser d'ici quelques semaines dans le cadre d'un logiciel que je souhaite développer.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Pourquoi ne pas utiliser une lib C++, vu que c'est le forum C++... ?
    Perso, j'ai utilisé sqlpp11 et sqlite_modern_cpp sur différents projets et j'en ai été plutôt content mais il en existe plein d'autres : https://github.com/SRombauts/SQLiteC...qlite-wrappers

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 637
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 637
    Par défaut
    Salut,

    Bien sur que c'est possible. Autrement, ce ne serait vraiment pas pratique

    Mais, pour cela, il va sans doute falloir ruser un peu

    La première chose, ce sera sans doute de créer une structure représentant un enregistrement dans la base de donnée, car ce sera plus facile. De toutes manières, il y a fort à parier qu'une telle structure te sera particulièrement utile pour le reste de ton programme.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    struct Person{
        int id;
        std::string firstname;
        std::string lastname;
        int age;
        std::string town;
        double amount;
    }
    la deuxième chose de se connectrer à une base de donnée, car tout dépendra de cette connection
    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
    /* Il nous faut le nom de la base de données */
    std::string dbname{"MyDb"};
    /* Il faut un "handler" sur la base de donnée */
    sqlite3 * db= nullptr;
    /* On peut maintenant créer le handler */
    {
        auto result = sqlite3_open(dbname.data(), &db);
        /* et comme on a un code de vérification, autant l'utiliser */
        if(result != SQLITE_OK){
            /* créons un message d'erreur explicite */
            std::string error{"unable to connect to database "};
            error.append(dbName)
                 .append(sqlite3_errmsg(db));
            /* il faut fermer la base de donnée malgré tout */
            sqlite3_close(db);
            /* on peut lancer une exception maintenant */
            throw std::runtime_error(error);
        }
    }
    Tu remarquera que j'ai placé tout le code entre une paire d'accolades. C'est fait expres de manière à ce que la variable result n'existe réellement qu'entre ces deux accolades, afin de pouvoir la réutiliser par la suite (en la déclarant à chaque fois que nécessaire)

    La troisième chose sera de préparer l'instruction. Nous allons avoir besoin de deux éléments:
    • Une chaine de caractères qui représente l'instruction (sans les valeurs) et
    • un (pointeur sur une donnée de type) sqlite3_stmt représentant l'instruction qui sera effectivement effectuée

    Cela devrait prendre une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    /* Il faudra adapter les noms des champs dans dans les première parenthèses, 
     * je me suis basé sur les noms des champs de la structure
     */
    std::string insert{"INSERT INTO Person (id, firstname, lastname, age, touwn, amount) VALUES(?,?,?,?,?,?)"};
    sqlite3_stmt * indsertStmt = nullptr;
    Ensuite, il faudra demander à sqlite d'utiliser notre chaine de caratères insert pour créer l'instruction en attente de binding, sous une forme qui sera proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    {
        auto result = sqlite3_prepare_v2(db, insert.data(), insert.size(), &insertStmt, nullptr);
        /* Et, comme on a un code de vérification, autant l'utiliser */
        if(result!= SQLITE_OK){
             /* n'oublions pas de fermer la base de données */
            sqlite3_close(db);
            throw std::runtime_error("unable to prepare sqlite INSERT statement");
        }
    }
    Arrivé à ce point, il "n'y a plus" qu'à effectuer le binding des informations de notre structure et à exécuter la requète:
    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
    /* Considérons que nous avons placé toutes les personnes dans
    un tableau proche de */
    std::vector<Person> tabPersons;
    /* Nous pouvons les parcourir l'une après l'autre sous la forme de
    for(auto const & it : tabPersons){ 
        int result; // il va falloir s'assurere que toutes les données sont bindées */
        result = sqlite3_bind_int(indsertStmt,1, it.id);
        if(result != SQLITE_OK){
           /* il faut libérer la mémoire de insertStmt */
          sqlite3_finalize(insertStmt);
           /* on ferme la db */
            sqlite3_close(db);
           throw std::runtime_error("unable to bind person's id for insertion");
        }
        result = sqlite3_bind_text(indsertStmt,2, it.firstname.data(), it.firstname.size()); 
        if(result != SQLITE_OK){
           /* il faut libérer la mémoire de insertStmt */
          sqlite3_finalize(insertStmt);
           /* on ferme la db */
            sqlite3_close(db);
           throw std::runtime_error("unable to bind person's first name for insertion");
        }
        result = sqlite3_bind_text(indsertStmt,3, it.lastname.data(), it.lastname.size()); 
        if(result != SQLITE_OK){
           /* il faut libérer la mémoire de insertStmt */
          sqlite3_finalize(insertStmt);
           /* on ferme la db */
            sqlite3_close(db);
           throw std::runtime_error("unable to bind person's last name for insertion");
        }
        result = sqlite3_bind_int(indsertStmt,4, it.age);
        if(result != SQLITE_OK){
           /* il faut libérer la mémoire de insertStmt */
          sqlite3_finalize(insertStmt);
           /* on ferme la db */
            sqlite3_close(db);
           throw std::runtime_error("unable to bind person's age for insertion");
        }
        result = sqlite3_bind_text(indsertStmt,5, it.town.data(), it.lastname.size()); 
        if(result != SQLITE_OK){
           /* on ferme la db */
            sqlite3_close(db);
           throw std::runtime_error("unable to bind person's town for insertion");
        }
        result = sqlite3_bind_double(indsertStmt,6, it.amount);
        if(result != SQLITE_OK){
           /* il faut libérer la mémoire de insertStmt */
          sqlite3_finalize(insertStmt);
           /* on ferme la db */
            sqlite3_close(db);
           throw std::runtime_error("unable to bind person's amount for insertion");
        }
        /* Si on arrive jusqu'ici, insertStmt est maintenant près à insérer un nouvel
         * enregistrement
         */
        result = sqlite3_step(insert_stmt);
        if(result != SQLITE_DONE){ // si la requete ne renvoie pas DONE, y a eu un problème
            /* créons un message d'erreur explicite */
            std::string error{"unable to connect to database "};
            error.append(dbName)
                 .append(sqlite3_errmsg(db));
            /* il faut fermer la base de donnée malgré tout */
            sqlite3_close(db);
            /* on peut lancer une exception maintenant */
            throw std::runtime_error(error);
       }
    }
    Bien sur, tout cela représente une approche purement procédurale.

    Il serait sans doute (surement, même) d'utiliser une approche plus "orientée objet" pour obtenir ce résultat.

    Le framework Qt, propose déjà une telle approche, qui pourrait se limiter (pour reprendre la même structure) sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
      QSqlQuery query;
        query.prepare("INSERT INTO person (id, firstname, lastname, age, touwn, amount) VALUES(?,?,?,?,?,?)");
        query.bindValue(0, it.id);
        query.bindValue(1, it.firstname);
        query.bindValue(2, it.lastname);
        query.bindValue(3, it.age);
        query.bindValue(4, it.town);
        query.bindValue(5, it.amount);
        query.exec();
    Et nous pourrions tout à fait nous amuser à faire notre propre binding, mais ca, ce sera pour "plus tard" (si il t'intéresse)
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

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

Discussions similaires

  1. Insertion de données avec php5
    Par Ludo75 dans le forum Langage
    Réponses: 3
    Dernier message: 24/08/2010, 15h18
  2. Insertion de donnée avec apostrophe
    Par jiojioforever dans le forum Langage SQL
    Réponses: 7
    Dernier message: 03/05/2007, 10h47
  3. [MySQL] Insertion de données avec apostrophes dans ma base
    Par kawther dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 01/04/2007, 09h06
  4. Insertion de données avec Posgretsql
    Par djibril dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 18/05/2004, 11h23
  5. Réponses: 2
    Dernier message: 14/05/2004, 14h32

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