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 :

Champ Auto Increment avec interbase


Sujet :

Bases de données Delphi

  1. #1
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2010
    Messages
    104
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2010
    Messages : 104
    Points : 85
    Points
    85
    Par défaut Champ Auto Increment avec interbase
    Bonjour à tous,
    Je ne suis pas débutant en delphi, mais je suis complètement débutant en base de données.
    Je me suis lancé dans un premier projet base de données avec Interbase.
    Je suis arrivé à créer ma base de données et j'ai créé ma table avec ce code :
    MyIBQuery.SQL.Add('CREATE TABLE DONNE '
    + '(NUM int not null,'
    + 'DATA VarChar(13))'
    + ';');
    MyIBQuery.ExecSQL;
    Ma question est la suivante, je voudrais transformer mon champ "NUM" en champ auto incrémenté ou bien en créer un nouveau.
    Interbase ne dispose pas de champ auto incrémenté.
    Après des recherches sur internet, j'ai vu qu'il fallait passer par des Trigger et des générateurs;
    InterBase doesn't have a convenient AutoInc datatype like Paradox, so we have to do a little bit of work to get this functionality. Start out by creating an Integer field that is appropriate for the size of the values you want in your AutoInc field. From there, we need a trigger to calculate the value for the field:

    CREATE TRIGGER autoinc FOR tablename
    BEFORE INSERT AS
    BEGIN
    NEW.autoinc_field_nane = GEN_ID(generator_name, 1);
    END

    We aren't done yet. We need a persistent location to store the current AutoInc value. InterBases way to deal with this is called a generator:

    CREATE GENERATOR generator_name;
    SET GENERATOR generator_name TO x;
    J'ai essayé de l'incorporer dans l'instruction SQL qui me sert à créer ma table mais j'ai plein d'erreurs.
    Un coup de main serait le bienvenu.
    Merci

    Jean-Louis

  2. #2
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    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 784
    Points : 5 915
    Points
    5 915
    Par défaut
    Bonjour,
    Citation Envoyé par illuch Voir le message
    Ma question est la suivante, je voudrais transformer mon champ "NUM" en champ auto incrémenté ou bien en créer un nouveau.
    Interbase ne dispose pas de champ auto incrémenté.
    Après des recherches sur internet, j'ai vu qu'il fallait passer par des Trigger et des générateurs;
    Ce n'est pas la peine d'aller aussi loin...
    Developpez dispose d'une qu'il est régulièrement conseillé de lire et où cette problématique est décrite... : http://interbase.developpez.com/faq/...es-generateurs

    Citation Envoyé par illuch Voir le message
    J'ai essayé de l'incorporer dans l'instruction SQL qui me sert à créer ma table mais j'ai plein d'erreurs.
    Le composant TIBQuery que vous avez utilisez ne peut exécuter qu'une instruction SQL à la fois, mais pas un script, c.a.d. un ensemble d'instructions SQL.
    Soit vous itérez le traitement pour chaque instruction SQL, en s'assurant qu'elles ont bien été exécutées, soit vous utilisez le composant adéquat capable de traiter un script TIBScript (installer une mise à jour des composant IBX s'avèrera peut-être nécessaire...
    Philippe.

  3. #3
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2010
    Messages
    104
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2010
    Messages : 104
    Points : 85
    Points
    85
    Par défaut
    Merci de votre réponse
    Citation Envoyé par Ph. B. Voir le message
    Developpez dispose d'une qu'il est régulièrement conseillé de lire et où cette problématique est décrite... : http://interbase.developpez.com/faq/...es-generateurs
    oui, je l'avais vu ... mais je n'ai pas su le mettre en oeuvre
    Citation Envoyé par Ph. B. Voir le message
    Bonjour,
    Le composant TIBQuery que vous avez utilisez ne peut exécuter qu'une instruction SQL à la fois, mais pas un script.
    C'est l'explication des erreurs rencontrées...

    Voilà donc ce que je viens de faire suite à vos explications.

    1°) Je créé ma base de données et une table grâce à ce code trouvé dans l'aide delphi.

    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
    procedure TForm1.CreateDatabase(Nom_Base: TFilename);
    var MyIBDataBase: TIBDatabase;        
        MyIBQuery: TIBQuery;             
        MyIBTransaction: TIBTransaction;  
    begin
      MyIBDataBase := TIBDatabase.Create(nil);
      MyIBQuery := TIBQuery.Create(nil);
      MyIBTransaction := TIBTransaction.Create(nil);
      try
        MyIBDataBase.DatabaseName := Nom_Base;
        MyIBDataBase.SQLDialect := 3;
        MyIBDataBase.Params.Clear;
        MyIBDataBase.Params.Add('USER "aaaaaaaa"');        
        MyIBDataBase.Params.Add('PASSWORD "bbbbbbbb"'); 
        MyIBDataBase.Params.Add('PAGE_SIZE 4096');
     
        MyIBDataBase.CreateDatabase;
        MyIBDatabase.Connected := true;
        MyIBTransaction.DefaultDatabase := MyIBDataBase;
        MyIBQuery.Database := MyIBDatabase;
        MyIBQuery.Transaction := MyIBTransaction;
        try
          MyIBQuery.SQL.Add('CREATE TABLE DONNE '
          + '(NUM int not null,'                                    // C'est le champ que je voudrais transformé en champ auto incrémenté
          +' DATA VarChar(13))'      
          + ';');
     
          MyIBQuery.ExecSQL;
     
          {...}
          { Reste de la création de la base par script SQL en dur ou récupérer dans un fichier }
          {...}
     
          MyIBTransaction.Commit;
        except
          MyIBTransaction.Rollback;
        end;
        MyIBDataBase.Connected := false;
      finally
        FreeAndNil(MyIBQuery);
        FreeAndNil(MyIBTransaction);
        FreeAndNil(MyIBDataBase);
      end;
    end;
    Cette partie de code fonctionne parfaitement.

    2°) Création du générateur et du trigger

    J'utilise donc un TIBScript pour exécuter des scripts sql

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    procedure TForm1.Button4Click(Sender: TObject);
    begin
         IBScript1.Script.clear;
         IBScript1.Script.Add('CREATE GENERATOR AUTONUM;');
         IBScript1.Script.Add('SET GENERATOR AUTONUM TO 1;');
         IBScript1.ExecuteScript;
     
         IBScript1.Script.clear;
         IBScript1.Script.add('CREATE TRIGGER MYGENE FOR DONNE ACTIVE '+
          'BEFORE INSERT POSITION 0 AS begin IF (NEW.NUM IS NULL) THEN '+
          'NUM= GEN_ID(AUTONUM,1);END;');
         IBScript1.ExecuteScript;
    end;
    après avoir créé ma base, dès que je clique sur Button1 pour créer le générateur et le trigger,
    j'ai le message d'erreur suivant :

    Le projet MonProjet.exe a déclenché la classe d'exception EIBinterBaseError avec le message 'unsuccessful metadata update
    DEFINE GENERATOR failed
    attempt to store duplicate value (visible to active transcastions) in unique index "RBS$INDEX_11" '.

    Où est mon erreur ?
    Est-ce la bonne méthode pour créer un générateur et le trigger ?
    Merci de votre aide

    Jean-Louis

  4. #4
    Membre expérimenté
    Avatar de ouiouioui
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2006
    Messages
    984
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Août 2006
    Messages : 984
    Points : 1 418
    Points
    1 418
    Par défaut
    Bonjour,

    crée d'abord tes generator, puis tu execute à nouveau ibscript avec les valeurs de generator que tu veux.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    IBScript1.Script.clear
    IBScript1.Script.Add('CREATE GENERATOR AUTONUM;');
    IBScript1.Script.add('CREATE TRIGGER MYGENE FOR DONNE ACTIVE ' +
      'BEFORE INSERT POSITION 0 AS begin IF (NEW.NUM IS NULL) THEN ' +
      'NUM= GEN_ID(AUTONUM,1);END;');
    IBScript1.ExecuteScript;
    
    IBScript1.Script.clear;
    IBScript1.Script.Add('SET GENERATOR AUTONUM TO 1;');
    IBScript1.ExecuteScript;
    c'est plus simple d'utiliser un outil pour tester les requêtes, par ex SQL Manager Lite, si sa fonctionne tu met en code.
    Il existe 3 sortes de gens: ceux qui savent compter et ceux qui ne savent pas.

  5. #5
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2010
    Messages
    104
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2010
    Messages : 104
    Points : 85
    Points
    85
    Par défaut
    Merci de la réponse,

    Citation Envoyé par ouiouioui Voir le message
    crée d'abord tes generator, puis tu execute à nouveau ibscript avec les valeurs de generator que tu veux.
    Mais comment créer d'abord les générateurs ?
    Faut-il procéder comme je l'avais fait par un script sql ou d'une autre façon ?
    J'ai testé le script modifié que tu m'as proposé, mais j'ai toujours la même erreur.
    J'en suis toujours au même point.

    JLouis

    E

  6. #6
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 036
    Points : 40 941
    Points
    40 941
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    je pense surtout que cette étape ne devrait pas s'exécuter par programme, sauf s'il s'agit d'une première installation, sans avoir de bonnes sécurités, à savoir tests d'existence des divers éléments.

    Je me suis lancé dans un premier projet base de données avec Interbase.
    quelle version ? (cela peut avoir son importance quant aux mots clés)

    Où est mon erreur ?
    il doit manquer un COMMIT; entre la création du générateur et son initialisation
    Est-ce la bonne méthode pour créer un générateur et le trigger ?
    Oui, quoique je trouve ce dernier quelque peu succinct, que se passerait-il si la valeur était renseignée et supérieure à la SEQUENCE ?

    j'utilise plutôt le générateur suivant
    Code SQL : 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
     
    --CREATE GENERATOR GEN_PRODUITS_ID;
    --COMMIT;
    SET TERM ^ ;
    CREATE TRIGGER PRODUITS_BI FOR PRODUITS ACTIVE
    BEFORE INSERT POSITION 0
    AS
    DECLARE VARIABLE tmp DECIMAL(18,0);
    BEGIN
      IF (NEW.PRO IS NULL) THEN
        NEW.PRO = GEN_ID(GEN_PRODUITS_ID, 1);
      ELSE
      BEGIN
        tmp = GEN_ID(GEN_PRODUITS_ID, 0);
        if (tmp < NEW.PRO) then
          tmp = GEN_ID(GEN_PRODUITS_ID, NEW.PRO-tmp);
      END
    END^
    SET TERM ; ^

    Si toutefois tu veux garder l'utilisation du script je te conseille la méthode suivante :

    Crée ta base (une base)avec un Outil Graphique (GUI) comme IBEXPERT, IBCONSOLE etc...
    Crée ensuite le générateur, la table, le trigger , extrait ensuite le DDL de cette base et tu auras un script nickel

    une autre solution, pour un programme d'installation sans passer par un script est de faire une restauration d'un backup d'une base de données vide (backup des métadatas uniquement)
    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

Discussions similaires

  1. [Requête] creation de table avec un champ auto incrementé
    Par lucke_34 dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 30/04/2020, 23h18
  2. Comment créer un champ auto increment avec netbeans
    Par une_tite_question dans le forum NetBeans
    Réponses: 4
    Dernier message: 25/04/2008, 17h17
  3. Champ auto increment
    Par webbulls dans le forum Bases de données
    Réponses: 9
    Dernier message: 21/04/2004, 16h07
  4. Remise à zero champ auto-incrementé (SQL Server)
    Par James85 dans le forum Langage SQL
    Réponses: 6
    Dernier message: 26/01/2004, 09h23
  5. Nom du champs auto-incrementé
    Par norroy dans le forum Requêtes
    Réponses: 2
    Dernier message: 17/06/2003, 18h30

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