1. #1
    Membre habitué
    Profil pro
    Inscrit en
    mars 2010
    Messages
    146
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2010
    Messages : 146
    Points : 138
    Points
    138

    Par défaut Accès à une base SQLITE3 - Ajout des enregistrements

    Bonjour à tous,

    Je suis désolé de revenir sur un problème déjà ressassé mais dont je n'arrive pas à trouver la solution bien que j'aie déjà fait ce genre de choses. Je cherche à entrer des données dans une base SQLITE3 (Lazarus version 1.6.4.- Windows10 -Zeos 1.7.4 Stable paquets mis à jour par GVasseur).
    Je veux accéder à une base SQLITE3 pour y ajouter des enregistrements. La base a été créée auparavant par code sans problème. Pour cela je dispose de 3 composants :
    un Composant TZConnection (ZC_InfoPromo), un composant TZ_QUERY (ZQ_InfoPromo) et un DataSource (DataSEcoPromo). Devant renseigner 3 tables de la base, j'ai construit, en faisant appel à un "RadioGroup" le code suivant :

    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
     
    procedure TF_InfoPromo.Bt_OKEcolPromoClick(Sender: TObject);
        Var MessOuv : String ;
        Var TablTravail : String ;
        Var ChoixTablactiv : String ;
        Var FlagOuvTbl : String ;
    begin
       BaseActive := F_GestBase.Ed_BaseActive.Text ;
       Ed_FlagMsg.Text := 'Coucou !' ;
       FlagOuvTbl := 'OuvrNon' ;
     
     
        Try ;
            Case (RG_ChoixTbl1.ItemIndex) of
              0: Begin ;  // Instructions pour la table Ecole
              ChoixTablactiv := 'Select * From Ecole'  ;
              TablTravail :=  'Ecole' ;
              FlagOuvTbl := 'OuvrOui' ;
                 End;
              1: Begin ;  // Instructions pour la table InfoPromo
              ChoixTablactiv := 'Select * From InfoPromo' ;
              TablTravail := 'Promo' ;
              FlagOuvTbl := 'OuvrOui' ;
                 End;
               2: Begin ;  // Instructions pour la table Sections
              ChoixTablactiv := 'Select * From section' ;
              TablTravail := 'Sections' ;
              FlagOuvTbl := 'OuvrOui' ;
                 End;
              End ;
                // *** Instructions d'accès à la Base à traiter
                if(FlagOuvTbl = 'OuvrOui') Then
                   Begin
                     // base à traiter
                     ZC_EcoPromo.Connected:= False ;
                     ZC_EcoPromo.Database:= BaseActive ;
                     ZC_EcoPromo.Connected:= True ;
                     Ed_FlagMsg.Text := TablTravail;
                     // ****  Accès aux tables
                     ZQ_EcoPromo.Active := False ;
                     ZQ_EcoPromo.Connection := ZC_EcoPromo;
                     ZQ_EcoPromo.DataSource := DataSEcoPromo;
                     ZQ_EcoPromo.Active := False ;
                     ZQ_EcoPromo.SQL.Clear ;
                     ZQ_EcoPromo.SQL.Text := ChoixTablActiv  ;
                     ZQ_EcoPromo.ExecSQL ;
                     Ed_FlagMsg.Text := TablTravail ;
                     F_GestBase.visible := False ;
                   end;
           Except
               MessOuv := 'Problème d''accès à la table ' + TablTravail  + ' de la base' + #13 + BaseActive ;
               ShowMessage (MessOuv) ;
        End;
    End;
    Sachant que le DataSource correspondant à valeur Dataset à ZQ_EcoPromo
    A l’exécution de ce code, J'accède bien aux contrôles à renseigner mais aucune lise à jour des enregistrements n'est effectuée. Les datasets sont inactifs. SI au lieu d'utiliser

    j'utilise

    j'ai une erreur SIGSEGV qui s'affiche.
    Je dois donc avoir omis de déclarer comme active la table à renseigner mais comment faire ?

    Merci de vos réponses.

    R.O.

  2. #2
    Membre éprouvé
    Profil pro
    Développeur informatique
    Inscrit en
    janvier 2010
    Messages
    427
    Détails du profil
    Informations personnelles :
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : janvier 2010
    Messages : 427
    Points : 966
    Points
    966

    Par défaut

    Bonjour

    Ne peux tu regarder la pile et trouver à quel endroit se produit l'erreur ?

    Sans le code complet, il est difficile de comprendre ce que tu cherches à faire exactement.

    Tu dis "ajouter des enregistrements" ? Mais avec quelle requête ?
    On ne peut pas insérer en exécutant seulement une requête SELECT...
    Soit on exécute une requête INSERT soit éventuellement on appelle les méthodes .append et .post de l'objet TZQuery.

    Une autre chose curieuse est l'utilisation de chaines avec différents noms pour ce qui semble concerner la même table : 'InfoPromo' et 'Promo'; 'Section' et 'Sections'.

    Il serait aussi prudent de fermer l'instruction case.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    case
        1: Begin ;  // Instructions pour la table InfoPromo
              ChoixTablactiv := 'Select * From InfoPromo' ;
              TablTravail := 'Promo' ;
              FlagOuvTbl := 'OuvrOui' ;
            End;
        {...}
    else
       raise Exception.Create ('erreur... ! ');
    end;
    Cordialement,
    Tintinux

    Initiateur de Gestinux, une comptabilité gestion open-source, pour Linux, Windows et Mac OS.
    Une version stable et une autre en développement, avec Lazarus : vous pouvez aider à la tester, la traduire et à la développer.

  3. #3
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique
    Inscrit en
    janvier 2007
    Messages
    8 553
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : janvier 2007
    Messages : 8 553
    Points : 19 959
    Points
    19 959
    Billets dans le blog
    4

    Par défaut

    Bonjour,

    pour mettre à jour des données ou insérer des données à partir d'un ZQuery il faut lui associer un TZUpdateQuery.

    extrait de mon tutoriel sur les composants ZEOS toujours à l'état brouillon et qui risque de le rester
    Élément incontournable pour une TZQuery modifiable , TZUpdateSQL encapsule un ensemble d'instructions SQL permettant d'actualiser l'ensemble de données . Une requête multitables est par définition selon ,la norme SQL-92, en lecture seule , TZUpdateSQL permet de contourner ce que certains peuvent considérer comme une limitation.
    La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein
    J'entends et j'oublie. Je vois et je me souviens. Je fais et je comprends . Confucius
    Si votre seul outil est un marteau, vous aurez tendance a ne voir que des clous

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    mars 2010
    Messages
    146
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2010
    Messages : 146
    Points : 138
    Points
    138

    Par défaut Ajout d'enregistrements à une table - Suite

    Bonjour et merci à Tintinux pour avoir répondu,

    Mon interrogation manque certainement de clarté, aussi je vais tenter de préciser. En fait, je reprends, pour tenter de l'améliorer un programme que j'ai fait il y a 3 ou 4 ans. Ce programme est basé sur 3 formulaires permettant de gérer une base de données comportant 4 tables.
    Le premier formulaire me sert à identifier ou à créer la base sur laquelle on va travailler et à créer par code chacune des tables Cela fonctionne bien (composants Zeos , Table Sqlite3). Une fois la table créée, une option permet de l'ouvrir et en même temps, le formulaire 1 est masqué et le formulaire 2 devient visible. Le nom complet (chemin+ Nom + extension .db3) est mémorisé dans une variable globale du second formulaire.
    J'ai déposé sur ce second formulaire des TDBEdit pour entrer les données à sauvegarder pour les tables Ecole, InfoPromo et Section. La quatrième table qui s’appelle Eleve devant être gérée par troisième formulaire. En principe le nombre d'enregistrements de la table Ecole est en général unique, celui des tables InfoPromo et section est assez faible.
    Pour gérer l'accès successif aux diverses tables j'ai donc déposé sur le second formulaire qui ferme après avoir géré les options de mise à jour des tables par l'utilisation d'un un composant RadioGroup dont les les 3 premières options permettent d'accéder aux 3 tables déjà nommées, la quatrième option permettant d'accéder au formulaire 3 tout en masquant le formulaire 2 et en sauvegardant pour les utiliser dans le formulaire 3 certaines valeurs du formulaire 2 .
    En voulant écrire le code le plus concis possible, je n'ai déposé sur le formulaire 2 qu'un seul TZConnection, un TZQUERY et un DataSource e, me disant qu'il serait possible, par code et en modifiant les références du DataSource (propriété Dataset) et au SQL du TZQUERY d'accéder aux diverses tables pour y stocker des données. La navigation entre les données et les fonctions d'ajout, modification, suppression étant assurées par un TDBNavigator. .
    Depuis,j'ai réalisé que je faisais une erreur et je suis donc revenu à une conception plus classique avec un TZConnection (référence à une base) et un TZQUery et un TadataSouce par table. Ce qui donne le code suivant pour la table Ecole, un code similaire devant être construit pour chacune des deux autres tables.
    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
    procedure TF_InfoPromo.Bt_OKEcolPromoClick(Sender: TObject);
        Var MessOuv : String ;
        Var TablTravail : String ;
        Var ChoixTablactiv : String ;
        Var FlagOuvTbl : String ;
    begin
     
       Ed_FlagMsg.Text := 'Coucou !' ;
       FlagOuvTbl := 'OuvrNon' ;
     
     
        Try ;
            Case (RG_ChoixTbl1.ItemIndex) of
              0: Begin ;  // Instructions pour la table Ecole
              BaseActive := F_GestBase.Ed_BaseActive.Text ;
              // base à traiter
              ZC_EcoPromo.Connected:= False ;
              ZC_EcoPromo.Database:= BaseActive ;
              ZC_EcoPromo.Connected:= True ;
              // ****  Accès aux tables
              ED_FlagMsg.Text :=  'Ecole' ;
              FlagOuvTbl := 'OuvrOui' ;
              DBNavPromo.DataSource := DataSEcole ;
              ZQ_TblEcole. Active  := False  ;
           //    ZQ_TblEcole.Sql.Text := 'INSERT INTO "Ecole" (*) Values (*)' ;   // Code en construction C'est là que se situe le prbl.
              ZQ_TblEcole. Open ;
              DBNavPromo.DataSource := DataSEcole ;
     
                 End;
              1: Begin ;  // Instructions pour la table InfoPromo
    // La suite du code.....
    Dans le passé j'ai déjà utilisé la ligne de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ZQ_TblEcole.Sql.Text := 'Select * From Ecole' ;
    à ce niveau et cela fonctionnait correctement.
    Il y a peut-être quelque chose de changé dans la version actuelle de Lazarus ou dans la façon de gérer SQLite ?

    En attendant je vais tente d'avancer avec la suggestion vos Suggestions (Tintinus et SergioMaster)

    Merci

    R.O.

  5. #5
    Membre confirmé

    Inscrit en
    juin 2012
    Messages
    305
    Détails du profil
    Informations forums :
    Inscription : juin 2012
    Messages : 305
    Points : 473
    Points
    473

    Par défaut

    Et en remplaçant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ZQ_TblEcole. Active  := False  ;
    par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ZQ_TblEcole.clear; 
    ZQ_TblEcole.close;
    ?

  6. #6
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique
    Inscrit en
    janvier 2007
    Messages
    8 553
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : janvier 2007
    Messages : 8 553
    Points : 19 959
    Points
    19 959
    Billets dans le blog
    4

    Par défaut

    Bonjour,

    Quelque soit la méthode, une ou plusieurs requêtes pour pouvoir modifier un ensemble de données obtenu par requête il vous faut un TZUpdateSQL.
    Vous auriez utilisé un TZTable qui encapsule en fait ce composant de manière discrète (les options de updatechanged et wheremode se chargeant de construire les différentes requêtes) le problème ne se poserait pas.
    De fait en utilisant un SELECT * from Unetable l'utilisation d'un TZQuery est je dirais "sujet à caution" puisque vous récupérez de toute manière toute la table.

    je n'ai pas tout compris concernant votre interface et votre code et, à mon avis vous vous compliquez la tâche ! et les éléments de structure des tables me manque pour vraiment saisir ce que vous voulez exactement

    Afin de donner un exemple je pars sur le shéma suivant : une seule forme pour gérer les trois tables

    composants visibles
    un DBGrid, un DBNavigator, un choix (combobox ou autre) de table à gérer
    composants non visibles
    TZConnection, TZQuery, TZUpdateSQL, TDataSource

    Le TZQuery avec les propriétés Connection=TZConnection et UpdateObject=TZUpdateSQL
    le DataSource lié à TZQuery

    DBGrid lié au DataSource, de même que le TDBNavigator
    voici une démarche :

    1. indiquez la propriété UpdateObjet de votre TZQuery : ZQuery1.UpdateObject:=Update_SQL
    2. Double cliquez sur le TZUpdateSQL et un wizard vous permet de générer puis à l'occasion modifier les 3 SQL de bases (vous pourrez même en profiter pour vérifier mes assertions sur les options citées plus haut)
    3. Si vous n'êtes pas un pro du SQL vous obtenez ainsi les différents SQL à utiliser
    4. Toujours dans le cas d'une seule requête+ un seul TZUpdateSQL il vous faut alors mettre ces requêtes en constantes et répéter l'opération pour les 2 autres tables, vous obtenez alors 9 constantes contenant les instructions SQL



    Lorsque vous utilisez alors l'index du choix il vous suffit alors de modifier les DeleteSQL.Text,InsertSQL.Text,ModifySQL.text pour correspondre à votre Query
    si je reprend en gros votre code cela donnerait quelque chose de ce genre :
    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
    const DSQL0 = 'DELETE FROM TABLE0 WHERE KEY=:old_KEY';
    const ISQL0 = 'INSERT INTO TABLE0(col1,col2,col3) VALUES (:col1,:col2,:col3)';
    const USQL0 = 'UPDATE TABLE0 SET col1=:col1, col2=:col2, col3=:col3) where key=:old_code';
    ....  
     
    Query1.Active:=False;
    case choixtableindex of   // ou tout autre choix 
      0 : begin
              Query1.SQL.Text:='SELECT * FROM TABLE0'; 
              Update_SQL.DeleteSQL.Text:=DSQL0;
              Update_SQL.InsertSQL.Text:=ISQL0;
              Update_SQL.ModifySQL.Text:=USQL0;
              .....     
           end;
      1 : 
      2 : 
    end; 
    Query1.Active:=True;
    P.S. dans votre code vous mettez ZC_EcoPromo.Database:= BaseActive ; ce qui semble être votre TZConnection mais pourquoi dans le case ?
    En admettant que vous ayez un base par établissement/région/ ? contenant les tables Ecole,Section, infoPromo lorsque vous travaillez sur une base vous n'en changez pas
    La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein
    J'entends et j'oublie. Je vois et je me souviens. Je fais et je comprends . Confucius
    Si votre seul outil est un marteau, vous aurez tendance a ne voir que des clous

  7. #7
    Membre éprouvé
    Profil pro
    Développeur informatique
    Inscrit en
    janvier 2010
    Messages
    427
    Détails du profil
    Informations personnelles :
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : janvier 2010
    Messages : 427
    Points : 966
    Points
    966

    Par défaut

    Bonjour

    Dans le dernier code il y a :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ZQ_TblEcole. Active  := False  ;
    //    ZQ_TblEcole.Sql.Text := 'INSERT INTO "Ecole" (*) Values (*)' ;   // Code en construction C'est là que se situe le prbl.
    ZQ_TblEcole. Open ;
    C'est déjà mieux, mais il faut enlever le commentaire et lister les champs entre les 1ères parenthèses, et mettre soit des constantes, soit plutôt des paramètres que l'on renseigne avant d'exécuter.

    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ZQ_TblEcole.Sql.Text := 'INSERT INTO Ecole (champ1,champ2) Values (:P1, :P2)' ;
    ZQ_TblEcole.Parameters[0].AsString := edit1.text;
    ZQ_TblEcole.ParamByName('P2').AsString := edit2.text; {autre forme}
    ZQ_TblEcole.ExecSql;
    C'est ZQ_TblEcole.ExecSql et non Open. Il faut ensuite rafraichir la requête SELECT pour y afficher les nouvelles données.

    C'est ce qui me parait le plus simple, mais on peut aussi faire autrement et de plusieurs façons, en particulier utiliser un TZUpdateSQL ou les propriétés UpdateSql d'une query, comme le suggère maître Sergio, quoique cela ne me semble pas indispensable ni plus clair. On peut aussi utiliser la Query SELECT et y faire .append, renseigner les champs et terminer par .post, ce que fait automatiquement le DbNavigator.

    Je ne vois d'ailleurs pas pourquoi vous n'utilisez pas des TZTable et un DbNavigator, ce qui est de loin le plus simple. Le fait d'avoir plusieurs tables ne pose a priori aucun problème.

    En tous cas, à ma connaissance, rien n'a changé sur ce sujet récemment.
    Cordialement,
    Tintinux

    Initiateur de Gestinux, une comptabilité gestion open-source, pour Linux, Windows et Mac OS.
    Une version stable et une autre en développement, avec Lazarus : vous pouvez aider à la tester, la traduire et à la développer.

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    mars 2010
    Messages
    146
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2010
    Messages : 146
    Points : 138
    Points
    138

    Par défaut Accès à une table Sqlite-3

    Bonjour à tous et merci pour les réponses qui m'ont été apportées.
    En définitive, et après être revenu à une conception de base du renseignement de la base de données soit : Une table est renseignée par un formulaire contenant des TDBEDIT ou des composants similaires ; A chaque table est associé un TZConnection, un TZQuery et un Tdatasource et un TDBNavigator la séquence donnée en exemple ci après fonctionne bien à la condition expresse que les Propriétés et Evènements associés à ces divers contrôles soient correctement renseignés .
    Exemple de Code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     //************** Connection à la base de Données
      BaseActive2 := F_GestBase.Ed_BaseActive.Text ;
      ZC_Promocree.Connected:= False ;
      ZC_Promocree.Database:= BaseActive2 ;
      ZC_Promocree.Connected:= True ;
    Puis, plus loin dans le code et avant de renseigner les TDBEdit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     // ****  Accès à la table Promo : Paramétrage ZQuery
                     ZQ_Promocree.Active := False ;
                     ZQ_Promocree.SQL.Clear ;
                     ZQ_Promocree.SQL.Text := 'Select * From InfoPromo' ;
                     ZQ_Promocree.Open ;
    Les propriétés des divers contrôles étant fixées à :

    Pour le TZConnection
    Database : laissé vierge (il est renseogné par code)
    Connected à true
    Protocol à sqlite-3
    Aucun évènement validé

    Pour le TZQuery :
    Evènements : Connection Le TZConnection
    Propriétés : Connection Le TZConnection

    Pour le TDataSource
    Propriétés : Le Dataset à TZQuery
    Évènements : idem

    Pour le TDBEdit :
    Propriétés :
    le Datasource au Datasource de la feuille
    Le DataField : renseigné manuellement au nom du champ de la table concernée.
    Evènements Le Datasource de la feuille
    AutoEdit et Enabled à True.


    Cordialement

    R.O.

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

Discussions similaires

  1. [Débutant] Ajout des enregistrement d'une base de donnes acces via une autre base acces
    Par nefzawi dans le forum Visual Studio
    Réponses: 0
    Dernier message: 14/04/2013, 22h42
  2. Réponses: 3
    Dernier message: 26/10/2008, 12h10
  3. Réponses: 3
    Dernier message: 08/06/2008, 22h08
  4. Gestion des accès à une base de données
    Par white_tiger dans le forum Sécurité
    Réponses: 7
    Dernier message: 07/02/2007, 01h39

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