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

Bases de données Delphi Discussion :

Master-Detail en sql avec Firedac pour SQLite


Sujet :

Bases de données Delphi

  1. #1
    Membre averti
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Février 2007
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Ardennes (Champagne Ardenne)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Février 2007
    Messages : 13
    Par défaut Master-Detail en sql avec Firedac pour SQLite
    Bonjour,

    Je gualère depuis un bon moment sur l'update d'une table détail en SQL sur une base SQLite.
    Lorsque je clique sur le bouton de sauvegarde pour la mise à jour d'une ligne de la table "Service_Contrat", j'ai une erreur sans message qui stope la procédure.
    Je n'ai aucune idée d'où vient mon erreur.
    Je m'en remets donc aux spécialistes de Delphi.
    Merci par avance de me débloquer.
    François
    Master-Detail.zip

  2. #2
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 999
    Par défaut
    Aucune structure de table fournie, ni aucun code, ni même le message d'erreur.
    Uniquement un lien vers un ZIP douteux dont personne en 2025 ne prendra le risque de cliquer dessus.

    Bonne chance.

  3. #3
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 658
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 658
    Billets dans le blog
    65
    Par défaut
    Bonjour,

    Il y a plusieurs choses que je vais reprocher, je m'en excuse d'avance, je sors juste de ma caverne.

    Tout d'abord un point de détail, quelle version de Delphi ?
    Plus gros, la nécessité des JVCL et des Raize components qui me laisse sur le carreau question debug (je n'ai aucune des ces suites d'installées)

    et enfin le fait que le chemin de la bdd soit codé en dur (dans ConnectData_module)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FDConnection.Params.Database := 'C:\Logiciels Delphi\test Base\Compilé\Base\test_bon.db';
    nécessite une mise en garde aux testeurs volontaires : "Décompresser dans le répertoire C:\Logiciels Delphi"
    NB : je ne vois pas l'utilité du FDtransaction à priori tout est pris par défaut revoir au besoin si vraiment nécessaire

    Concernant la forme, je vais surtout me pencher sur l'utilisation de Firedac avec un mot d'ordre : simplifier et améliorer, être plus SQL "aware".

    En commençant par le dernier : j'ai horreur des SELECT * FROM TABLE, une bonne "hygiène" est de déclarer les champs SELECT col1,col2,.. FROM TABLE pour une optimisation de la demande
    surtout que sans indication conforme il se peut très bien que les instructions de mises à jour générées par Firedac soient par la suite erronnées !

    Simplifier et améliorer : cela ce fera grâce à Firedac et ses syntaxes
    exemples :
    tablesDatamodule_unit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    ServiceAgent_FDQuery.SQL.Text :=  'Select * from Service_Agent;';
    ServiceContrat_FDQuery.SQL.Text :=  'Select * from Service_Contrat WHERE id_agent=:id_agent;';
    ServiceAgent_FDQuery.Open;
    ServiceContrat_FDQuery.Open;
    
    sera modifiable en 2 lignes.
    NB. le point virgule dans le SQL.text n'est pas une si bonne idée que ça car Firedac accepte plusieurs instructions SQL séparées et permet de sauter d'un SQL à l'autre (mais je m'égare)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    procedure TTables_DataModule.Tables_Initialise;
    begin
      ServiceAgent_FDQuery.Oen('Select * from Service_Agent');
      ServiceContrat_FDQuery.Open('Select * from Service_Contrat WHERE id_agent=:id_agent');
    end;
    Second point toujours dans la même unité puisque les instructions sont identiques, autant utiliser la procédure Tables_initialize dans la procédure Tables_OnCreate.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure TTables_DataModule.Tables_OnCreate(Sender: TObject);
      begin
        ServiceAgent_FDQuery.Connection := Connect_DataModule.FDConnection;
        ServiceContrat_FDQuery.Connection := Connect_DataModule.FDConnection;
        ServiceAgent_FDQuery.Transaction := Connect_DataModule.FDTransaction;
        ServiceContrat_FDQuery.Transaction := Connect_DataModule.FDTransaction;
        ServiceAgent_DataSource.DataSet := ServiceAgent_FDQuery;
        ServiceContrat_DataSource.DataSet := ServiceContrat_FDQuery;
        Tables_Initialize;
      end;
    Nota : au design, ServiceContrat_FDQuery devrait avoir le bon SQL, actuellement il ouvre toute la table.

    Prenons ensuite les étapes prises au hazard de mes lectures
    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
    procedure TMain_Form.DeleteAgent_OnClick(Sender: TObject);
      var
        str : Integer;
    
      begin
        begin //// en trop 
    
      // Si aucun enregistrement
      if Agent_DBGrid.Datasource.Dataset.RecordCount = 0 then
        Exit;
      //// bloc utile ?
    
      // Si il y a un enregistrement courant
      if Agent_DBGrid.Datasource.Dataset.RecNo >= 0 then //// j'ai horreur de l'utilisation de recno trop aléatoire
        if MessageDlg(R_supprimer, MtConfirmation, MbOkCancel, 0) = mrOk
        then
           begin
           str := Tables_Datamodule.ServiceAgent_FDQuery.FieldByName('Id_Agent').AsInteger;
           Tables_Datamodule.ServiceAgent_DataSource.DataSet.Active := False;
           Tables_Datamodule.ServiceAgent_FDQuery.SQL.Clear;
           Tables_Datamodule.ServiceAgent_FDQuery.SQL.Text := 'delete from Service_Agent where id_Agent = '+ quotedStr(IntToStr(str))+';' ;
             Try
               Tables_Datamodule.ServiceAgent_FDQuery.ExecSQL ;
               Connect_Datamodule.FDConnection.StartTransaction;
               ShowMessage('3');
               Connect_DataModule.FDTransaction.Commit;
     //// FDTransaction semble être en autostart donc inutile   
    
             except
               on e: Exception do
                 begin
                   e.Message  := e.Message + 'Suppression annulée.';
                   Connect_Datamodule.FDTransaction.Rollback;
                   raise e;
                 end;
             end;
           end
         else
           begin
           //
           end;
         //
    
         //Refresh de la grille après suppression
         Agent_DBGrid.DataSource.DataSet.Refresh;
         Agent_DBGrid.Refresh;
    
       end;
     end;
    je propose plus simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure TMain_Form.DeleteAgent_OnClick(Sender: TObject);
    begin
        if MessageDlg(R_supprimer, MtConfirmation, MbOkCancel, 0) = mrOk
        then  begin
             ServiceAgent_FDQuery.Connection.ExecSQL('delete from Service_Agent where id_Agent =:i',
                                                                             [Tables_Datamodule.ServiceAgent_FDQuery.FieldByName('Id_Agent').AsInteger]);
             Tables_Datamodule.ServiceAgent_FDQuery.Open(); // fait les refresh nécessaires, pas sûr de l'utilité mais c'est plus court que ce que j'ai lu ;) 
        end;
     
    end;
    mais, sans SQL, un simple aurait pu suffire il me semble. Après tout, il s'agit d'une version mono-utilisateur puisque SQLite
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TMain_Form.DeleteAgent_OnClick(Sender: TObject);
    begin
        if MessageDlg(R_supprimer, MtConfirmation, MbOkCancel, 0) = mrOk
        then  begin
             ServiceAgent_FDQuery.Delete;
        end;
    j'ai pris ensuite un UPDATE, toujours au hazard
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        Tables_Datamodule.ServiceAgent_FDQuery.SQL.Text := 'UPDATE Service_Agent SET civilite=' + quotedstr(Civilite_ComboBox.Text) +', nom=' + quotedstr(Nom_Edit.Text) +', Prenom=' + quotedstr(Prenom_Edit.Text) +', Statut=' + quotedstr(Statut_ComboBox.Text) +', Categorie=' + quotedstr(Categorie_ComboBox.Text) +', fonction=' + quotedstr(Fonction_Edit.Text) +', DateArrivee=' + quotedstr(FormatDateTime('yyyy-mm-dd', DateArrivee_DateTimePicker.Date)) +', DureeContrat=' + quotedstr(DureeContrat_SpinEdit.Text) +', Present=' + quotedstr(IntToStr(Ord(Present_CheckBox.Checked))) + ' where id_agent=' +  intToStr(iAgent);
    D'une part on aurait pu utilisé un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Tables_Datamodule.ServiceAgent_FDQuery.Edit;
    Tables_Datamodule.ServiceAgent_FDQuery.FieldByname('civilite').asString:=Civilite_ComboBox.Text;
    .....
    Tables_Datamodule.ServiceAgent_FDQuery.Post;
    ou alors, écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     var SQLUpdate:='UPDATE Service_Agent SET civilite=?, nom=?, Prenom=?, Statut=?, Categorie=?, fonction=?, DateArrivee=?, DureeContrat=?, Present=? where id_agent=?';
     Tables_Datamodule.ServiceAgent_FDQuery.Connexion.ExecSQL(SQLUpdate,                                                                                            
    [Civilite_ComboBox.Text,
     Nom_Edit.Text,
     Prenom_Edit.Text,                                                                                                
     Statut_ComboBox.Text, 
     Categorie_ComboBox.Text,
     Fonction_Edit.Text,
     DateArrivee_DateTimePicker.Date, // là j'ai un doute n'ayant pas encore regardé la structure de la table
     DureeContrat_SpinEdit.value, // à vérifier la synatxe pour avoir un integer
     Present_CheckBox.Checked,
     iagent 
    ]);
    inconvénient de cette formulation, ne pas se planter dans l'ordre et le nombre d'arguments.
    J'ai utilisé la forme "anonyme" des arguments ( le '?').

    Voilà j'ai fait ma BA du jour, c'est déjà beaucoup pour une sortie d'estivage.

    Plusieurs choses me surprennent :
    - une trop grande isolation des unités voire par exemple les deux datamodules compliquant le problème AMHA
    - une non utilisation des composants liés aux données (TDBxxxxxx) et encore n'ai-je regardé que Agent_unit
    - la classe ServiceAgent qui, AMHA embrouille les choses sauf si tout n'est pas dit ?
    - toujours sur le forme agent, le besoin de tout repositionner me semble étrange mais encore une fois sauf si tout n'est pas dit ?
    etc...
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  4. #4
    Membre Expert
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 542
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 70
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 542
    Billets dans le blog
    10
    Par défaut
    Si tu envoies la structure de la base je peux t'aider. Je travaille sur un sujet similaire

  5. #5
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 658
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 658
    Billets dans le blog
    65
    Par défaut
    Sérieux, la BDD est fournie (dans le zip \Master-Detail\test Base\Compilé\Base) donc il est très aisé de récupérer la structure !

    --
    -- Fichier généré par SQLiteStudio v3.4.17 sur lun. juil. 21 13:57:17 2025
    --
    -- Encodage texte utilisé : System
    --
    PRAGMA foreign_keys = off;
    BEGIN TRANSACTION;

    -- Tableau : Service_Agent
    CREATE TABLE IF NOT EXISTS Service_Agent (
    id_Agent INTEGER PRIMARY KEY AUTOINCREMENT
    NOT NULL,
    Civilite VARCHAR (7),
    nom VARCHAR (30) NOT NULL,
    prenom VARCHAR (40) NOT NULL,
    statut VARCHAR (20),
    categorie VARCHAR (1),
    fonction VARCHAR (100),
    datearrivee DATE,
    dureecontrat INTEGER,
    present BOOLEAN
    );


    -- Tableau : Service_AvisCTRA
    CREATE TABLE IF NOT EXISTS Service_AvisCTRA (
    id_AvisCTRA INTEGER PRIMARY KEY AUTOINCREMENT
    NOT NULL
    UNIQUE,
    id_Agent INTEGER NOT NULL
    CONSTRAINT Agent REFERENCES Service_Agent (id_Agent) ON DELETE CASCADE,
    Departement CHAR (90),
    Commune CHAR (80),
    [Lieu-dit] CHAR (120),
    Date_CTRA DATE,
    Rapporteur CHAR (150),
    Autre_repertoire_avisCTRA BOOLEAN,
    Repertoire_AvisCTRA CHAR (200),
    Avis_CTRA CHAR (100),
    Link_AvisCTRA CHAR (300),
    View_AvisCTRA INTEGER
    );


    -- Tableau : Service_CarnetHabillement
    CREATE TABLE IF NOT EXISTS Service_CarnetHabillement (
    id_CarnetHabillement INTEGER PRIMARY KEY AUTOINCREMENT
    NOT NULL,
    id_agent INTEGER CONSTRAINT Agent REFERENCES Service_Agent (id_Agent) ON DELETE CASCADE,
    Casque CHAR,
    Casquette CHAR,
    Bonnet CHAR,
    Casque_oreille CHAR,
    ItemIndex_Parka4en1 INTEGER,
    Parka_4en1 CHAR,
    ItemIndex_Softcel INTEGER,
    SoftCel CHAR,
    ItemIndex_Gilet INTEGER,
    Gilet CHAR,
    ItemIndex_Veste INTEGER,
    Veste CHAR,
    ItemIndex_VestepluieHV INTEGER,
    VestePluie_HV CHAR,
    ItemIndex_Chasuble INTEGER,
    Chasuble CHAR,
    ItemIndex_TShortMancheCourte INTEGER,
    TShortMancheCourte CHAR,
    ItemIndex_TShortMancheLongue INTEGER,
    TShortMancheLongue CHAR,
    ItemIndex_PoloMancheCourte INTEGER,
    PoloMancheCourte CHAR,
    ItemIndex_PantalonTravail INTEGER,
    Pantalon_Travail CHAR,
    ItemIndex_PantalonPluie INTEGER,
    Pantalon_Pluie CHAR,
    ItemIndex_PantalonChaud INTEGER,
    Pantalon_Chaud CHAR,
    ItemIndex_GantLavage INTEGER,
    Gant_Lavage CHAR,
    ItemIndex_Gantmanutention INTEGER,
    Gant_manutention CHAR,
    ItemIndex_ChaussureSecurite INTEGER,
    Chaussure_securite CHAR,
    Modele_Homme BOOLEAN,
    Modele_Femme BOOLEAN,
    ItemIndex_Bottepluie INTEGER,
    Botte_pluie CHAR,
    ItemIndex_Bottechaude INTEGER,
    Botte_chaude CHAR,
    Guetre CHAR
    );


    -- Tableau : Service_Contrat
    CREATE TABLE IF NOT EXISTS Service_Contrat (
    id_contrat INTEGER PRIMARY KEY AUTOINCREMENT
    NOT NULL,
    id_agent INTEGER CONSTRAINT Agent REFERENCES Service_Agent (id_Agent) ON DELETE CASCADE,
    filiere VARCHAR (30),
    categorie_hierarchique VARCHAR (1),
    cadre_emploi VARCHAR (70),
    statut VARCHAR (20),
    date_debut DATE,
    date_fin DATE,
    duree INTEGER,
    Avant_terme BOOLEAN,
    Date_anticipee DATE,
    observation TEXT (200)
    );


    -- Tableau : Service_Formation
    CREATE TABLE IF NOT EXISTS Service_Formation (
    id_Formation INTEGER PRIMARY KEY AUTOINCREMENT
    NOT NULL,
    id_Agent INTEGER NOT NULL
    CONSTRAINT Agent REFERENCES Service_Agent (id_Agent) ON DELETE CASCADE,
    Intitule VARCHAR (100),
    id_organisme INTEGER (5),
    Organisme CHAR (50),
    Date_Debut DATE,
    Date_Fin DATE,
    Duree FLOAT,
    Autre_repertoire_Attestation BOOLEAN,
    repertoire_Attestation CHAR (300),
    Attestation CHAR (100),
    Link_Attestation CHAR (300),
    View_Attestation INTEGER
    );


    -- Tableau : Service_Habilitation
    CREATE TABLE IF NOT EXISTS Service_Habilitation (
    id_habilitation INTEGER PRIMARY KEY AUTOINCREMENT
    NOT NULL
    UNIQUE,
    id_agent INTEGER CONSTRAINT Agent REFERENCES Service_Agent (id_Agent) ON DELETE CASCADE,
    designation VARCHAR (100),
    date_obtention DATE,
    duree_validite INTEGER,
    date_renouvellement DATE,
    Autre_repertoire_attestation BOOLEAN,
    Repertoire_attestation CHAR (200),
    Attestation CHAR (100),
    Link_attestation CHAR (300),
    View_attestation INTEGER,
    Autre_repertoire_habilitation BOOLEAN,
    Repertoire_habilitation CHAR (200),
    Habilitation CHAR (100),
    Link_habilitation CHAR (300),
    View_habilitation INTEGER
    );


    -- Tableau : Service_Publication
    CREATE TABLE IF NOT EXISTS Service_Publication (
    id_publication INTEGER PRIMARY KEY AUTOINCREMENT
    NOT NULL
    UNIQUE,
    id_agent INTEGER CONSTRAINT Agent REFERENCES Service_Agent (id_Agent) ON DELETE CASCADE,
    intitule_publication CHAR (200),
    [co-auteurs] CHAR (255),
    editeur CHAR (70),
    collection CHAR (70),
    annee_publication INTEGER (4),
    Autre_repertoire_publication BOOLEAN,
    Repertoire_Publication CHAR (200),
    Publication CHAR (100),
    Link_publication CHAR (300),
    View_publication INTEGER
    );


    COMMIT TRANSACTION;
    PRAGMA foreign_keys = on;
    ce qui me permet de voir que certaines colonnes sont calculées ?
    exemple : -- Tableau : Service_Formation
    Date_Debut DATE,
    Date_Fin DATE,
    Duree FLOAT,
    peu explicite, durée si duree est en jours plus compréhensible si en heures ?
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  6. #6
    Membre averti
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Février 2007
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Ardennes (Champagne Ardenne)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Février 2007
    Messages : 13
    Par défaut
    Bonjour tous,

    La structure des 2 tables sont ainsi :
    la master :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    CREATE TABLE [Service_Agent](
      [id_Agent] INTEGER PRIMARY KEY AUTOINCREMENT, 
      [Civilite] VARCHAR(8), 
      [nom] VARCHAR(30), 
      [prenom] VARCHAR(40), 
      [statut] VARCHAR(20), 
      [categorie] VARCHAR(1), 
      [fonction] VARCHAR(100), 
      [datearrivee] DATE(10), 
      [dureecontrat] INTEGER(2), 
      [present] BOOLEAN);
    La détail :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    CREATE TABLE [Service_Contrat](
      [id_contrat] INTEGER PRIMARY KEY AUTOINCREMENT, 
      [id_agent] INTEGER CONSTRAINT [Agent] REFERENCES [Service_Agent]([id_Agent]) ON DELETE CASCADE, 
      [filiere] VARCHAR(30), 
      [categorie_hierarchique] VARCHAR(1), 
      [cadre_emploi] VARCHAR(70), 
      [statut] VARCHAR(20), 
      [date_debut] DATE(10), 
      [date_fin] DATE(10), 
      [duree] INTEGER(2), 
      [Avant_terme] BOOLEAN(1), 
      [Date_anticipee] DATE(10), 
      [observation] TEXT(200));
    Je pense avoir trouvé mon problème majeur hier dans la nuit. Dans ma réelle appli, Delphi devait se mélanger les pinceaux car le chemin de la base la base est déclarée de l'unité Connect_datamodule_Unit à la mano pour la propriété database du compo FDTConnection et aussi dans la liste des propriétés du composant. Les 2 chemins ne pointaient pas au même endroit.
    Le bout de l'appli que j'ai mis en pièce jointe, n'est qu'une partie du source complet.
    J'ai découvert cela à 2h30 du mat', la fatigue étant là, j'ai coupé mes moteurs pour y regarder aujourd'hui les yeux dans les trous.
    J'ouvre mon PC à l'instant donc je n'ai pas encore approfondis les choses.

    @SergioMaster Je prends bonne note de vos remarques que l'appliquerai ensuite dès que mon update de table détail fonctionnera. Je préfère traiter problème par problème que d'en créer de nouveaux en gérant tout d'un bloc. Je m'appuie beaucoup sur du code exsistant et je refais beaucoup par mémétisme. Nulle part je n'ai vu que l'on pouvais lancer une requête SQL en ouvrant en même temps le query.
    A l'origine, l'application fonctionne sous Lazarus. C'est pour le fun que je refais sous Delphi.
    Je compléterai ce post pour vous confirmer ou infirmer que c'était bien la double saisie non identique du chemin de la base que posait problème. En fonction de mes recherche, j'avais un message qui me disait que le commande ne pouvait pas être appliquée sur un query fermé.
    Merci SergioMaster pour l'approfondissement de mes connaissances.
    A bentôt
    François

  7. #7
    Membre Expert
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 542
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 70
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 542
    Billets dans le blog
    10
    Par défaut
    Excuses, j'avais pas vu le fichier. J'ai pu faire tourner ton appli compilée avec Delphi 12.3. J'aurais peut être une approche différente. Je reste à ta disposition. Alain

  8. #8
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 658
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 658
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par linuxien08 Voir le message
    Nulle part je n'ai vu que l'on pouvais lancer une requête SQL en ouvrant en même temps le query.
    c'est firedac qui le permet

    A l'origine, l'application fonctionne sous Lazarus. C'est pour le fun que je refais sous Delphi.
    le challenge eut été de faire ça en FMX et cibler non seulment windows mais Android
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  9. #9
    Membre Expert
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 542
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 70
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 542
    Billets dans le blog
    10
    Par défaut
    J'ai refait une version dossier Alain
    La base reste inchangée
    Mettre Le bon chemin pour la base
    Nom : Capture d’écran 2025-07-21 170441.png
Affichages : 93
Taille : 15,5 Ko
    Fichiers attachés Fichiers attachés

  10. #10
    Membre averti
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Février 2007
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Ardennes (Champagne Ardenne)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Février 2007
    Messages : 13
    Par défaut
    Hello tous,

    Erreur trouvée !
    En faisant un peu n'importe quoi j'ai obtenu en message que j'avais une erreur sql proche de la commande "where".
    En effet, une virgule de trop parasitait le code SQL du fait du copié-collé de chaque champ pour créer la commande globale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     Service_Datamodule.ServicePeriode_FDQuery.SQL.Text := 'UPDATE Service_Contrat SET filiere=' + quotedstr(Filiere_RzComboBox.Text) +', Categorie_Hierarchique=' + quotedstr(Categorie_RzComboBox.Text) +', Cadre_Emploi=' + quotedstr(CadreEmploi_RzComboBox.Text) +', Statut=' + quotedstr(Statut_RzComboBox.Text) +', Date_Debut=' + quotedstr(FormatDateTime('yyyy-mm-dd', DateDebut_RzDateTimeEdit.Date)) +', Date_Fin=' + quotedstr(FormatDateTime('yyyy-mm-dd', Datefin_RzDateTimeEdit.Date)) +', Duree=' + quotedstr(IntToStr(Round(DureeContrat_RzSpinEdit.Value))) +', Avant_Terme=' + quotedstr(IntToStr(Ord(AvantTerme_RzCheckBox.Checked))) +', Date_Anticipee=' + quotedstr(FormatDateTime('yyyy-mm-dd', DateAnticipee_RzDateTimeEdit.Date)) +', Observation=' + quotedstr(Observation_RzMemo.Text) + ', where id_Contrat=' +  intToStr(iContrat);
    Il faut donc ôter la virgule avant la clause where de la commande SQL ci-dessus.
    J'ai vu le comment de faire en FMX mais des composants open-source utilisés ne sont pas compatibles pour ce mode et le parc de PC au boulot est tout en Windows. C'est pas demain que l'administration passera en Linux!
    Sous Lazarus, je n'ai pas ce soucis, je pourrai le compiler pour Linux ensuite.
    Merci de votre aide.
    François

  11. #11
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 658
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 658
    Billets dans le blog
    65
    Par défaut
    C'est là où une "normalisation" du SQL et l'utilisation de paramètre est vraiment une bonne chose.
    Sans parler de l'injection de SQL qui me semble trop facile (à première vue) avec la syntaxe utilisée !
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

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

Discussions similaires

  1. Master/Detail avec SQLite en Firedac
    Par linuxien08 dans le forum SQLite
    Réponses: 0
    Dernier message: 20/07/2025, 16h01
  2. python et SQL avec DuckDB ou SQLITE : où sont stockées les tables?
    Par sqlbeginner dans le forum Général Python
    Réponses: 3
    Dernier message: 24/09/2023, 10h36
  3. [2014] Sql avec date pour IOS
    Par elepetit dans le forum Développement
    Réponses: 1
    Dernier message: 20/02/2015, 06h08
  4. Réponses: 11
    Dernier message: 08/10/2009, 11h33
  5. requete SQL avec rownum pour un tri
    Par lilsandy dans le forum SQL
    Réponses: 4
    Dernier message: 10/07/2007, 11h01

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