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 :

Erreur ajout enregistrement dans Firebird via dbExpress


Sujet :

Bases de données Delphi

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 40
    Par défaut Erreur ajout enregistrement dans Firebird via dbExpress
    Bonjour à tous,

    Je me décide à quitter le BDE pour découvrir firebird. J'ai débuté avec le tuto "officiel " ici sans aucun problème et tout fonctionne parfaitement.

    Seulement voila, je voudrais rajouter des enregistrement sans me servir du couple dbnavigator/dbgrid (directement par code) mais cela ne marche pô

    Je commence par rajouter un enreg dans ma table avec une requete du type :

    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
    with Sql do
     with Campagne do
      begin
        Close;
             s := '10';    // valeur en dur de ma cle primaire juste pour vous expliquer;
       ss := 'XXXXX';
        with Sql do
        begin
          Clear;
          Add('INSERT INTO CAMPAGNE');
          Add('  (CAMPAGNE, NOM_CAMPAGNE)');
          Add('  VALUES (' + QuotedStr(s) + ',' + quotedstr(ss) + ')');
        end;
     
        Try
          ExecSql;
          frmMain.DBGrid1.Refresh;
          // display('  ok');
        except
          on e: Exception do
            showmessage('  *** pb_insert ' + e.Message);
        end;
      end; // with SqlQuery1
    Parfais, je valide avec un ApplyUpdates de mon clientdatatset et tout se passe bien.

    Seulement, mon dbgrid ne fait pas apparaitre le nouvel enreg, donc je tente d'ouvrir et de fermer mon sqlquery (sans aucun effet sur le refresh du dbgrid). Je tente alors d'ouvrir et de fermer mon clientdatatset et la erreur de cle primaire ('violation of primary or unique key constraint') incompréhensible car la cle est bien renseignée avec une valeur unique.

    Information : si je ferme et relance l'application, l'enregistrement que je viens de créer apparait bien dans mon dbgrid.

    Donc question : si quelqu'un peut me dire ou est mon erreur je prend (grave) ou si quelqu'un sait comment rafraichir ce foutu dbgrid ben je prend aussi

    Merci d'avoir lu jusque la, de prendre le temps de répondre si vous avez un début de solution et désolé pour le roman...

  2. #2
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 786
    Par défaut
    Bonjour

    La méthode Refresh que vous appelez est celle descendant de la classe TControl : Cela ne risque pas d'impacter votre jeu de données sous-jacent...
    frmMain.DBGrid1.DataSource.Dataset.Refresh; est plus approprié !
    Si vous êtes dans une méthode TfrmMain.Quelquechose, supprimez la référence à frmMain ou remplacez la par Self.

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    591
    Détails du profil
    Informations personnelles :
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2009
    Messages : 591
    Par défaut
    Bonjour,

    En examinant ton code, je n'ai vu aucun Commit.

    Sauf s'il est automatique, ce que personnellement j'évite dans une application Serveur client, il doit être effectué par du code.

    Cherches dans cette direction.

    A+

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 40
    Par défaut
    Merci à tous les deux pour vos réponses (pertinentes).

  5. #5
    Membre chevronné
    Avatar de alheuredudejeuner
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2005
    Messages : 376
    Billets dans le blog
    4
    Par défaut preferer agir sur le datatset et pas la grille pour le refresh
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    frmMain.DBGrid1.DataSource.Dataset.Refresh;
    *
    est plus approprié .

    Peut-être je suis dans l'erreur, mais je trouve préférable de travailler au niveau du dataset pour les rafraichissement plutôt que dbgrid élément visuel. Dans ce cas précis, monclientdataset refresh. Çà fonctionne avec le TSimpleClientDatatset.
    En cas de doute tester close puis open force parfois un refresh qui ne se fait pas.
    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
    var
    var
    MonsqlQuery : TsqlQuery
    begin
    MonsqlQuery :=TsqlQuery.create(self);
    with MonsqlQuery do
     with Campagne do
      begin
       connection := Monsqlconnection ;// TsqlConnection
        try
    Close;
             s := '10';    // valeur en dur de ma cle primaire juste pour vous expliquer;
       ss := 'XXXXX';
        with Sql do
        begin
          Clear;
          Add('INSERT INTO CAMPAGNE');
          Add('  (CAMPAGNE, NOM_CAMPAGNE)');
          Add('  VALUES (' + QuotedStr(s) + ',' + quotedstr(ss) + ')');
        end;
     
        Try
          ExecSql;
          frmMain.DBGrid1.Refresh;
          // display('  ok');
        except
          on e: Exception do
            showmessage('  *** pb_insert ' + e.Message);
        end;
       finally
       MonsqlQuery .free 
      end;
      end; // with SqlQuery1
    end;
    l’intérêt c'est que c'est commité tout seul par dbexpress, qu'on n'est pas obligé d'utiliser un composant, en dur sur la form, et que si ce code est répétitif avec plus ou moins de variantes, on peut se le mettre en procédure dans une unité.

    exemple :
    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
    procedure TfStocks.NewField(UneTable:String; UnChamp: String; UnType:String);
    var
      sqlNewTable: TSQLQuery;
    begin
      sqlNewTable:=TSQLQuery.Create(self);
      with sqlNewTable do
      begin
        SQLConnection:=dmVulcain.Vulcain_Stock;
        close;
        sql.clear;
        sql.add('select 1 from rdb$relation_fields where rdb$relation_name ='''+UneTable+''' and RDB$FIELD_NAME ='''+UnChamp+''';');
        try
          open;
          if FieldByName('CONSTANT').AsInteger = 1 then ELSE
          begin
            close;
            sql.Clear;
            Sql.Text := Format('ALTER TABLE %s ADD %s %s;', [UneTable, UnChamp, UnType]);
            try
              ExecSQL;
            Except
              On E:Exception do ShowMessage('Création Imposible :'+E.Message);
            end;
          end;
          finally
          sqlNewTable.Free;
        end;
      end;
    end;
    Je n'ai pas factorisé le sqlconnection, mais ça montre le principe.

    J'éviterai aussi la multiplication des with, ça m'a posé des problèmes.

    Cordialement

    André

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 40
    Par défaut
    Merci pour tes conseils André, ils vont m'être utiles. Malheureusement pour moi, la situation ne s'améliore pas. Voila le code que j’exécute :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SQLQuery1.Close;
        ss := 'XXXXX';
        SQLQuery1.Sql.clear;
        SQLQuery1.Sql.Add('INSERT INTO TEST (TEST_ID, TEST_NOM) VALUES (10,' + quotedstr(ss) + ')');
        Try
          SQLQuery1.ExecSql;
          dmmodule.ClientDataset1.ApplyUpdates(-1);
          frmmain.DBGrid1.DataSource.DataSet.Refresh;
        except
          on e: Exception do showmessage('  *** Aie !!' + e.Message);
        end;
    J'ai réduit le code au maximum et toujours impossible de rajouter un enregistrement. Dès que je déclenche le DBGrid1.DataSource.DataSet.Refresh" j'ai invariablement une erreur de contrainte ('violation of primary or unique key constraint *PK_TEST* on table TEST) alors que ma clé est bien unique et bien renseignée. ET ce qui est incompréhensible c'est que si je ferme et que je relance l’application les données ont bien étés enregistrées.

    Si quelqu'un a un début de solution je suis vraiment preneur

    Merci..

  7. #7
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 786
    Par défaut
    La commande dmmodule.ClientDataset1.ApplyUpdates(-1); est AMHA inutile.
    Elle doit être appelée quand on a ajouté, supprimé ou modifié un élément dans le clientdataset qui est un ensemble de données déconnecté.
    L'insertion réalisé via le composant SQLQuery1 se fait directement dans la table de la base de données.
    Rafraichir la grille doit être suffisant...
    La valeur 10 du TEST_ID est juste mis pour l'exemple ? car insérer 2 fois une clé unique aboutira à une violation de clé primaire...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SQLQuery1.Close;
        ss := 'XXXXX';
        SQLQuery1.Sql.clear;
        SQLQuery1.Sql.Add('INSERT INTO TEST (TEST_ID, TEST_NOM) VALUES (10,' + quotedstr(ss) + ')');
        Try
          SQLQuery1.ExecSql;
          //dmmodule.ClientDataset1.ApplyUpdates(-1);
          frmmain.DBGrid1.DataSource.DataSet.Refresh;
        except
          on e: Exception do showmessage('  *** Aie !!' + e.Message);
        end;

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 40
    Par défaut
    Bonjour à tous !

    Merci Ph.B. La valeur test_id = 10 est bien la pour l'exemple et est bien unique au moment de la saisie.

    Je viens de suivre tes indications et ca ne marche toujours pas. Le refresh du grid déclenche encore l'erreur ('violation of primary or unique key constraint *PK_TEST* on table TEST) Une question en passant, après mon SQLQuery1.ExecSql, le SQLQuery1.active = false si je le teste, c'est normal ca ??

    Je reste positif en espérant que ca soit une grosse bourde de ma part mais ca commence à devenir inquiétant. Dans tous les cas, merci à tous pour vos nombreuses réponses.

  9. #9
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 725
    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 725
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par fatdarron Voir le message
    Une question en passant, après mon SQLQuery1.ExecSql, le SQLQuery1.active = false si je le teste, c'est normal ca ??
    un ExecSQL n'ouvre pas de dataset , donc oui, c'est tout a fait normal !

    j'espere que SQLQuery1 est différent de frmmain.DBGrid1.DataSource.DataSet , sinon , au vue du source , y a un soucis car il a été fermé (ligne 1)

  10. #10
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 786
    Par défaut
    Bonjour,
    Citation Envoyé par fatdarron Voir le message
    Je viens de suivre tes indications et ca ne marche toujours pas. Le refresh du grid déclenche encore l'erreur ('violation of primary or unique key constraint *PK_TEST* on table TEST)
    Peut-on connaitre la définition de cette contrainte de clé ou d'unicité ? N'y en a-t-il pas une sur une autre colonne de la table ?
    Peut-on voir la définition complète de la table ?

    Si vous ne rafraichissez pas la grille après insertion, et que vous quittez l'application pour la relancer, est ce que cette insertion est alors visible ?

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 40
    Par défaut
    Bonjour à tous,

    Merci SergioMaster, j'avais un doute sur l'ouverture ou pas après un ExecSql.

    La définition sql de ma table (une seule clé définie sur une unique colonne TEST_ID)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    CREATE TABLE TEST 
    (
      TEST_ID               INTEGER         NOT NULL,
      TEST_NOM              VARCHAR(    50)  COLLATE UTF8,
     CONSTRAINT PK_TEST PRIMARY KEY (TEST_ID)
    );
    Ph.B : Dans le cas ou je ne fait pas de refresh de ma grille (et après un ApplyUpdates) et ou je ferme l'appli, tout se passe parfaitement et la nouvelle donnée est bien présente quand je relance.

    Pour infos (et j'aurais du le préciser avant) je suis sous Delphi 2010 avec les compos DBExpress et firebird comme BD

  12. #12
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 786
    Par défaut
    Bonjour,
    Citation Envoyé par fatdarron Voir le message
    Ph.B : Dans le cas ou je ne fait pas de refresh de ma grille (et après un ApplyUpdates) et ou je ferme l'appli, tout se passe parfaitement et la nouvelle donnée est bien présente quand je relance.
    J'en reviens à ma 1° remarque relative au clientdataset.

    Vous faites l'insertion directement dans la base de données via le composant TSQLQuery et une commande INSERT INTO... sans faire appel aux mécanismes du clientdataset.

    Le clientdataset travaille en mode déconnecté. Appeler la commande ApplyUpdates n'a de sens que si vous avez inséré, supprimé ou modifié des lignes dans ce clientdaataset et que vous souhaitez les répercuter vers la base de données. Est ce le cas ou votre clientdataset ne sert qu'à alimenter la grille et éventuellement changer les ordres de tri ?
    Dans ce dernier cas, supprimer le commande ApplyUpdates, le Refresh suffit...

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 40
    Par défaut
    Bonjour,

    Ph.B : Merci (une fois de plus) pour votre dernier message. Effectivement, si je ne m'obstine pas a ajouter les enregs directement dans la base par le SQLQuery et que je passe par un ClientDataset1.Append suivit après ajout des données par un applyUpdates tout marche parfaitement. Le grid rafraichis bien, montre les nouveaux enregs et plus d'erreur de clé.

    Merci à tous pour vos nombreuses réponses qui en bout de course m'ont permis de trouver le probléme (c'était dans la tête en fait ).....le BDE s'éloigne

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

Discussions similaires

  1. [AC-2007] Erreur ajout enregistrement via formulaire
    Par Méryam Sofi dans le forum Access
    Réponses: 2
    Dernier message: 16/06/2015, 19h35
  2. Erreur lors d'un INSERT sur une table dans Firebird via dbExpress
    Par matou7 dans le forum Bases de données
    Réponses: 4
    Dernier message: 03/04/2012, 17h40
  3. Réponses: 8
    Dernier message: 29/10/2007, 18h52
  4. [MySQL] problème ajout donnée dans BDD via php
    Par Skeud007 dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 30/05/2006, 00h41
  5. Réponses: 2
    Dernier message: 16/06/2005, 00h56

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