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

Delphi Discussion :

Auto-incrémententation avec Firebird


Sujet :

Delphi

  1. #1
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2016
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2016
    Messages : 71
    Points : 19
    Points
    19
    Par défaut Auto-incrémententation avec Firebird
    Bonjour
    Je veux créer une fonction qui fait auto-increment pour le champ OrderID = (numéro de facture).

    J'ai créé un générateur dans Firebird mais j'ai trouvé un problème :
    Lorsque je clique sur un nouvel enregistrement et qu'après je clique sur Annuler, il est toujours
    incrémenté (même si je clique sur annuler).
    J'ai utilisé cette fonction que j'ai trouvée sur ce forum :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function NewID(Table, code: String): Integer; 
    begin 
    with FDQOrder do 
    begin 
    Close; 
    SQL.Clear; 
    SQL.Add('select max(' + code + ') from ' + 'Orders'); 
    open; 
    Result := Fields[0].AsInteger + 1; 
    Close; 
    end; 
    end;
    Quand j'appelle la fonction :

    newID('Orders', 'OrderID'),

    j'ai une erreur :

    FDQOrder: field'ORDERID' not found.

    J'utilise Delphi Tokyo Firedac Firebird 3.0.

    SVP, dites-moi comment régler ce problème ou s'il y a une autre méthode pour générer les numéros ?

    Cordialement

  2. #2
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2016
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2016
    Messages : 71
    Points : 19
    Points
    19
    Par défaut
    Le programme est multi-utilisateurs et multiposte.

  3. #3
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 030
    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 030
    Points : 40 928
    Points
    40 928
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    je pars sur une constatation à valider FDQOrder : le préfixe FD me pousse à croire que vous utilisez Firedac ?

    il y a plusieurs choses que je note dans votre post.

    Tout d'abord parlons de l'auto-incrément :
    il y a trois manières de créer des champs auto-incréments avec Firebird (pour les versions inférieures à la version 3 deux seulement).

    Tout d'abord vous avez la possibilité d'utiliser l'ancien GENERATOR associé à un TRIGGER
    Ensuite le nouveau nom SEQUENCE toujours en association avec un TRIGGER
    https://firebird.developpez.com/faq/ chapitre 10 et 11
    https://firebirdsql.org/manual/gener...de-basics.html
    et enfin avec Firebird 3 un colonne GENERATED BY DEFAULT AS IDENTITY https://www.firebirdsql.org/file/doc...0-ddl-identity qui fait un incrément automatique sans trigger, le vrai champ auto-incrémenté en quelque sorte.

    Chacune de ces options a des plus et des moins, personnellement j'en reste au GENERATOR plus TRIGGER.
    En tout cas, l'avantage de des trois méthodes est qu'elles sont faites au moment de la transaction , l'incrément étant fait sur le serveur dans le cas d'utilisation d'un trigger c'est parfait pour un environnement utilisateur. L'inconvénient de ces méthodes, surtout en facturation, l'apparition de "trou" possibles.

    J'ai créé un générateur dans firebird mais j'ai trouver un problème:
    Lorsque je clique sur un nouvel enregistrement et qu'après je clique sur Annuler, il est toujours
    incrémenté même si je click sur annuler
    c'est tout à fait normal car vous avez du codé votre trigger sur le BEFORE INSERT d'où cette apparition de "trou"

    De plus vous oubliez, toujours si Firedac, une possibilité, déclarer votre colonne d'identification comme auto-incrément (dans ce cas il faut supprimer le trigger) et laisser firedac le gérer.
    (Firedac générera alors un SQL et la colonne sera égale à GEN_ID(NOM_GENERATEUR, 1) mais ceci, si vous ne faites pas de Validation n'incrémentera pas le genérateur contrairement au trigger)

    D'ailleurs à propos de facturation, j'ai eu un instant de doute car vous utilisez ORDERID = numero de facture, en plus vous faites un select from orders !
    Orders = Commandes, OrderiD= numero de commande (et là les trous ne sont pas importants) INVIDID ou BILLID from INVOICES eussent été plus approprié.



    Passons au SQL du Code, inconvénient dans un environnement multi utilisateurs repêché de cette manière un code peut planter (rare mais possible)

    votre code se simplifie

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function NewID(Table, code: String): Integer; 
    begin 
    with FDQOrder do 
    begin 
      Close; 
      SQL.Text:=Format('select max(%s)+1 NEWID from %s',[code,table]); 
      open; 
      Result := FieldbyName('NEWID').AsInteger; // ou Fields[0].asInteger 
      Close;
    end; 
    end;
    Cerise sur le gâteau vous pourriez aussi utiliser un FDQuery créé au runtime

    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
    function NewID(Table, code: String): Integer; 
    var QOrder : FDQuery;
    begin 
    QOrder:=FDQuery.Create;
    try
     with QOrder do 
     begin 
      Connection:=fdConnection1; 
      SQL.Text:=Format('select max(%s)+1 NEWID from %s',[code,table]); 
      open; 
      Result := FieldbyName('NEWID').AsInteger; // ou Fields[0].asInteger
      end;
    finally
      QOrder.Free;
    end; 
    end;
    encore y a t-il un petit problème ! qu'en est-il si max(code) est null (ceci ne serait pas un problème avec un générateur et un trigger)
    il faut modifier le "format" du SQL en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT COALESCE(max(%s),0)+1 NEW ID FROM %s

    vous pourriez aussi utiliser des macros

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT COALECSE(MAX(&Colonne),0) +1 NEWID FROM &Table

    et ne passer que les macros par exemple ainsi FDQOrder étant inscrit dans le DFM , SQL indiqué au dessus

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function NewID(Table, code: String): Integer; 
    begin 
    with FDQOrder do 
    begin 
      Close; 
      macrobyname('colonne').asRaw:=Code;
      macrobyname('Table').asRaw:=Table; 
      open; 
      Result := FieldbyName('NEWID').AsInteger; // ou Fields[0].asInteger 
      Close;
    end; 
    end;
    INCONVENIENTS de ces méthodes : attention à l'injection de SQL ! qu'est ce qu'il raconte
    une exemple si je passe en paramètre de votre fonction NewID('ORDER BY', 'ORDER') que croyez vous qu'il se passe ? à part un beau planton SQL !
    ou encore que se passerait-il si vous passiez NewId('1) from orders; DELETE','ORDERS');
    voilà une injection SQL qui pourrait faire mal !

    Mais je me pose la question quand même est-il vraiment utile d'utiliser des variables et donc un format ou des macros pour obtenir un nouveau numéro, pour moi c'est étrange
    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
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    Citation Envoyé par mrsimo7 Voir le message
    Bonjour
    je veux cree une fonction qui fait auto increment pour le champ OrderID = (numero de facture)

    J'ai créé un générateur dans firebird mais j'ai trouver un problème:
    Lorsque je clique sur un nouvel enregistrement et qu'après je clique sur Annuler, il est toujours
    incrémenté même si je click sur annuler
    ...
    c'est normal, l'enregistrement ne doit être créé que lorsque l'on clique sur OK, Annuler doit simplement ne rien faire.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  5. #5
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2016
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2016
    Messages : 71
    Points : 19
    Points
    19
    Par défaut
    Bonjour,
    Merci pour vos réponses.

    Citation Envoyé par SergioMaster Voir le message
    c'est tout à fait normal car vous avez du codé votre trigger sur le BEFORE INSERT d'où cette apparition de "trou"
    Tu as raison, le trigger était before insert.

    De plus vous oubliez, toujours si Firedac, une possibilité, déclarer votre colonne d'identification comme auto-incrément (dans ce cas il faut supprimer le trigger) et laisser firedac le gérer.
    (Firedac générera alors un SQL et la colonne sera égale à GEN_ID(NOM_GENERATEUR, 1) mais ceci, si vous ne faites pas de Validation n'incrémentera pas le genérateur contrairement au trigger)
    J'ai supprimé le trigger et j'ai configuré fdquery pour le gérer mais il donne des nombres négatifs -1, -2, -3....

    D'ailleurs à propos de facturation, j'ai eu un instant de doute car vous utilisez ORDERID = numero de facture, en plus vous faites un select from orders !
    Orders = Commandes, OrderiD= numero de commande (et là les trous ne sont pas importants) INVIDID ou BILLID from INVOICES eussent été plus approprié.
    OrderID = Numero de Facture
    Orders c'est la table des commandes où il y a le numéro de facture, le nom du client, la date ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function NewID(Table, code: String): Integer; 
    begin 
    with FDQOrder do 
    begin 
      Close; 
      SQL.Text:=Format('select max(%s)+1 NEWID from %s',[code,table]); 
      open; 
      Result := FieldbyName('NEWID').AsInteger; // ou Fields[0].asInteger 
      Close;
    end; 
    end;
    avec ce code j'ai l'erreur suivante :
    Nom : err1.png
Affichages : 577
Taille : 3,5 Ko

    Cerise sur le gâteau vous pourriez aussi utiliser un FDQuery créé au runtime

    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
    function NewID(Table, code: String): Integer; 
    var QOrder : FDQuery;
    begin 
    QOrder:=FDQuery.Create;
    try
     with QOrder do 
     begin 
      Connection:=fdConnection1; 
      SQL.Text:=Format('select max(%s)+1 NEWID from %s',[code,table]); 
      open; 
      Result := FieldbyName('NEWID').AsInteger; // ou Fields[0].asInteger
      end;
    finally
      QOrder.Free;
    end; 
    end;
    Avec ce code, j'ai l'erreur :

    E2003 Undeclared identifier: 'FDQuery'
    Je l'ai changé en TFDQuery,
    mais j'ai eu une autre erreur :
    QOrders:=tFDQuery.Create;
    E2035 Not enough actual parameters

    Pour les macros, je ne pas pu les tester .

    Mais je me pose la question quand même est-il vraiment utile d'utiliser des variables et donc un format ou des macros pour obtenir un nouveau numéro, pour moi c'est étrange
    Je suis débutant et je travaille sur des exemples.
    Si tu as une idée pour générer les numéros de factures en multi-utilisateurs (il faut que j'évite les doublons) tu vas me sauver .

    Table factures:
    ID:1
    OrderID:F2017001
    Client: Divers
    Date: 01/01/2017
    ...

    Pour Numéro de factures : F2017001
    F = Facture
    2017 = année encore
    001 = à incrémenter seulement si la facture a été validée.
    Merci d'avance.

  6. #6
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2016
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2016
    Messages : 71
    Points : 19
    Points
    19
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    c'est normal, l'enregistrement ne doit être créé que lorsque l'on clique sur OK, Annuler doit simplement ne rien faire.
    Tu as raison : le trigger que j'avais était before insert. Normalement, il doit être after post.

  7. #7
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 030
    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 030
    Points : 40 928
    Points
    40 928
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    désolé pour les quelques erreurs de code, mais il s'agissait de code écrit à la volée un dimanche après midi ....

    tout d'abord, l'erreur format
    là je ne comprend pas car je viens de tester ce bout de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure TForm8.Button1Click(Sender: TObject);
      function test(Code,table : String) : String;
        begin
         result:=Format('select max(%s)+1 NEWID from %s',[code,table]);
        end;
    begin
     Showmessage(Test('NEWID','ORDERS'));
    end;
    et ce sans erreurs pour ce qui est de l'instruction Format

    pour la cerise, codant à la volée, j'ai oublié d'enlever le noyau
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    function NewID(Table, code: String): Integer; 
    var QOrder : TFDQuery;
    begin 
    QOrder:=TFDQuery.Create(Self);
    pour continuer à tester j'ai donc créé une table ORDERS avec une colonne ID de type integer
    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
     
    procedure TForm8.Button1Click(Sender: TObject);
    var AQuery : TFDQuery;
      function test(Code,table : String) : String;
        begin
         result:=Format('SELECT COALESCE(MAX(%s),0)+1 NEWID FROM %s',[code,table]);
        end;
    begin
     Showmessage(Test('ID','ORDERS'));
     AQuery:=TFDQuery.Create(Self);
     try
       AQuery.Connection:=FDConnection1;
       AQuery.Open(Test('ID','ORDERS'));
       Showmessage(format('Nouveau numéro proposé %d',[AQuery.FieldByName('NEWID').asInteger]));
     finally
       AQuery.Free;
     end;
    end;
    ce code fonctionne et me renvoi bien "Nouveau numéro proposé 1".
    Vous remarquerez que j'utilise une nouvelle astuce pour le AQuery.Open j'y indique le SQL à exécuter !

    j'ai supprimer le trigger et j'ai configurer fdquery a le gérer mais il donne le negative -1, -2, -3....
    Oui mais comme vous n'indiquez pas comment vous avez fait ça (montre nous votre code, votre requête et les propriétés de celle-ci) difficile de dire ce qu'il en est. AMHA votre requête n'est pas correcte

    Un peu de pseudo analyse

    OrderID = Numero de Facture
    Orders c'est la table des commandes ou il ya numero de facture, nom client, date ...
    je veux bien que vous vouliez que OrderID soit le numéro de facture, c'est juste que un anglophone qui lirais votre code déduirai qu'il s'agit d'un identifant (id) de commande (order)

    Orders c'est la table des commandes ou il ya numero de facture, nom client, date ...
    si ORDERS est la table des commandes alors de mon point de vue le numéro de facture à l'intérieur ne devrait être qu'informatif (mis à jour au moment de la création de la facture dans un fichier à part FACTURES ou INVOICES pour rester dans l'anglais) et encore dans mon entreprise, une commande peut être livrée en plusieurs fois et donc faire l'objet de plusieurs factures ! Votre modèle de données plante dans ce cas.

    si tu a une idée pour générer les numéros de factures en multi-utilisateurs (il faut que j'évite les doublant) tu va me sauver
    Table factures:
    ID:1
    OrderID:F2017001
    Client: Divers
    Date: 01/01/2017
    tiens donc, vous n'êtes pas constant dans vos demande puisque là vous utilisez bien une table FACTURES et non la table Orders
    une raison de plus pour moi de vous signaler de changer le nom de la colonne en INVOICEID ou FACTUREID de façon à éviter toute confusion de genre.

    De plus, votre colonne ne peut pas être utilisée via un générateur puisqu'elle n'est pas numérique. Même s'il est facile d'en comprendre le principe !
    Votre colonne ID oui, elle peut être géré via une séquence, un générateur ou une IDENTITY car c'est un numéro normalement interne unique qui devrait être de type BIGINT.
    pour votre colonne numéro de facture (ORDERID ) il en va tout autrement !
    plusieurs solutions :
    1.soit vous décomposez en :
    TYPE_FACTURE (de type CHAR(1) contraintes 'F' pour Facture 'A' pour Avoir et même 'P' pour proforma)
    ANNEE_FACTURE (de type SMALLINT)
    NUMERO_FACTURE (de type SMALLINT) << c'est lui qu'il va falloir géré (on peut le faire soit via une séquence soit via une table contenant les derniers numéros utilisés)
    2.soit vous continuez avec cette colonne VARCHAR(8) en général dans ce cas on utilise une table contenant les derniers numéros utilisés

    Ensuite, comment allez vous déclarez la contrainte d'unicité ?
    si vous déclarez la/les colonnes faisant partie d'un index primaire donc NOT NULL ou simplement comme un INDEX unique les traitements ne seront pas forcément identiques ou dans le même ordre

    J'ai rajouté sciemment le type Proforma pour compliquer la donne. Si d'un point de vu administratif (comptabilité, fisc) les numéros doivent se suivre entre factures et avoir pour les proformas (factures en devenir) ils ont leur propre séquence. C'est là où, encore une fois une table contenant les derniers numéros utilisés est le plus courant

    Bref, je vous ai posé des bases de travail, mais avant de vous engager plus en avant, une bonne analyse est nécessaire
    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

  8. #8
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2016
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2016
    Messages : 71
    Points : 19
    Points
    19
    Par défaut
    Bonjour,
    je vous remercie infiniment pour tout l'effort que vous faite pour aider les gens

    [QUOTE=SergioMaster;9638607]
    function NewID(Table, code: String): Integer;
    var QOrder : TFDQuery;
    begin
    QOrder:=TFDQuery.Create(Self);
    [/CODE]
    pour continuer à tester j'ai donc créé une table ORDERS avec une colonne ID de type integer
    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
     
    procedure TForm8.Button1Click(Sender: TObject);
    var AQuery : TFDQuery;
      function test(Code,table : String) : String;
        begin
         result:=Format('SELECT COALESCE(MAX(%s),0)+1 NEWID FROM %s',[code,table]);
        end;
    begin
     Showmessage(Test('ID','ORDERS'));
     AQuery:=TFDQuery.Create(Self);
     try
       AQuery.Connection:=FDConnection1;
       AQuery.Open(Test('ID','ORDERS'));
       Showmessage(format('Nouveau numéro proposé %d',[AQuery.FieldByName('NEWID').asInteger]));
     finally
       AQuery.Free;
     end;
    end;
    ce code marche très bien en mode mono poste mais en multi postes quand deux utilisateur click sur nouvelle facture ils ont le meme numero
    comment je fait pour évité cela?


    Oui mais comme vous n'indiquez pas comment vous avez fait ça (montre nous votre code, votre requête et les propriétés de celle-ci) difficile de dire ce qu'il en est. AMHA votre requête n'est pas correcte
    voila les propriétés :
    Nom : err1.png
Affichages : 281
Taille : 22,6 Ko

    tiens donc, vous n'êtes pas constant dans vos demande puisque là vous utilisez bien une table FACTURES et non la table Orders
    une raison de plus pour moi de vous signaler de changer le nom de la colonne en INVOICEID ou FACTUREID de façon à éviter toute confusion de genre.
    j'ai écrit table facture juste pour vous facilité les details

    De plus, votre colonne ne peut pas être utilisée via un générateur puisqu'elle n'est pas numérique. Même s'il est facile d'en comprendre le principe !
    Votre colonne ID oui, elle peut être géré via une séquence, un générateur ou une IDENTITY car c'est un numéro normalement interne unique qui devrait être de type BIGINT.
    pour votre colonne numéro de facture (ORDERID ) il en va tout autrement !
    plusieurs solutions :
    1.soit vous décomposez en :
    TYPE_FACTURE (de type CHAR(1) contraintes 'F' pour Facture 'A' pour Avoir et même 'P' pour proforma)
    ANNEE_FACTURE (de type SMALLINT)
    NUMERO_FACTURE (de type SMALLINT) << c'est lui qu'il va falloir géré (on peut le faire soit via une séquence soit via une table contenant les derniers numéros utilisés)
    2.soit vous continuez avec cette colonne VARCHAR(8) en général dans ce cas on utilise une table contenant les derniers numéros utilisés
    si je fait une autre table details facture ca va être bien pour mono poste mais en multi poste je vais tomber toujours en numero dupliquer
    pour les F A P je préfère utiliser prefix et postfix et le numero généré au milieu car la plus part utilise FA0001/17 ... alors l'utilisateur utilise un prefix et postfix personnaliser

    Ensuite, comment allez vous déclarez la contrainte d'unicité ?
    si vous déclarez la/les colonnes faisant partie d'un index primaire donc NOT NULL ou simplement comme un INDEX unique les traitements ne seront pas forcément identiques ou dans le même ordre
    la loi marocaine oblige que les numéros doivent être dans le meme ordre

    J'ai rajouté sciemment le type Proforma pour compliquer la donne. Si d'un point de vu administratif (comptabilité, fisc) les numéros doivent se suivre entre factures et avoir pour les proformas (factures en devenir) ils ont leur propre séquence. C'est là où, encore une fois une table contenant les derniers numéros utilisés est le plus courant
    oui c'est obligé d'avoir les numéros successive comme je vous y expliquer en mode mono y'aura pas de problème avec la fonction que vous m'avez fait mais en multi utilisateurs ca ne marche pas

  9. #9
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 030
    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 030
    Points : 40 928
    Points
    40 928
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par mrsimo7 Voir le message
    la loi marocaine oblige que les numéros doivent être dans le même ordre
    je sais, j'y ai vécu/enseigné/développé 5 ans dans ce pays

    en mode mono y'aura pas de problème avec la fonction que vous m'avez fait mais en multi utilisateurs ca ne marche pas
    Je n'ai jamais écrit que c'était la solution, je l'ai même il me semble fortement déconseillé, je n'ai corrigé mon code quand dans un but "pédagogique" (ou plutôt pour corriger mes bêtises.
    ils ont le meme numero comment je fais pour éviter cela?
    Je prône toujours l'utilisation des triggers de Firebird, puisqu'au sein d'un trigger tout se fait dans une même transaction. Bien sûr il y a aussi la solution de la programmation multi tiers (datasnap) où, même en mode multi utilisateurs seul le programme sur le serveur accède à Firebird.

    D'expérience (d'avant la possibilité de la programmation multi-tiers) d'une application écrite avec D3 et BDE la solution Trigger+Table des Numéros de factures fonctionne très bien en multi-utilisateurs (plus de 17 ans de service, moyenne de 20 utilisateurs d'une PMI, mais 3 au max en facturation) les seuls "trous" (car il y en a toujours) sont dus aux utilisateurs qui supprime des factures, c'est donc à eux de gérer ce "trou". Je sais c'est dur ! mais du coup ils évitent et font un avoir .
    Nota. ce même programme est utilisé par 2 autres TPI (Très Petites Entreprise) dans le même secteur d'activité et, sauf erreur de manipulations (facturation automatique à l'intégration des bons de livraison externe au logiciel) tout de passe bien, toutefois comme il y a peu d'utilisateurs en même temps sur la facturation c'est moins sujet à problème de numérotation.


    si je fait une autre table details facture ca va être bien pour mono poste mais en multi poste je vais tomber toujours en numero dupliquer
    non, c'est exactement les mêmes principes qui doivent s'appliquer. Et, utilisez les bons termes Détails Facture pour moi cela veut dire lignes de factures

    pour donner un exemple : dans mon progiciel j'ai une Table Commandes qui contient l'en tête de commande (numero de client, adresse de livraison, date, mode de réglement etc...) une table Lignes de Commandes qui contient les articles commandés (article, prix_unitaire, qte, remise etc...). Une facture (numero de client, date, etc...) est stockée dans le fichier FACTURES et le détail de ces factures, les lignes dans un autre fichier, LIGNES_FACTURES (numero de ligne, commande, article,quantité, pu, remise, n°livraison etc..) une facture peut donc contenir plusieurs commandes, plusieurs livraison sur une même commande etc...

    pour les F A P je préfère utiliser prefix et postfix et le numero généré au milieu car la plus part utilise FA0001/17 ... alors l'utilisateur utilise un prefix et postfix personnaliser
    Raison de plus pour "éclater" le code de la facture et ne pas stocker l'affichage utilisateur.

    Pour ce qui est de l'utilisation de autoincfields de Firedac, il me semble que votre colonne ORDERID (OrderID:F2017001) n'est pas numérique donc, cela ne peut pas fonctionner
    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

  10. #10
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2016
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2016
    Messages : 71
    Points : 19
    Points
    19
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    je sais, j'y ai vécu/enseigné/développé 5 ans dans ce pays
    tu était dans quelle ville et quelle années ?


    Je n'ai jamais écrit que c'était la solution, je l'ai même il me semble fortement déconseillé, je n'ai corrigé mon code quand dans un but "pédagogique" (ou plutôt pour corriger mes bêtises.
    plutôt mes bêtises

    Je prône toujours l'utilisation des triggers de Firebird, puisqu'au sein d'un trigger tout se fait dans une même transaction. Bien sûr il y a aussi la solution de la programmation multi tiers (datasnap) où, même en mode multi utilisateurs seul le programme sur le serveur accède à Firebird.
    avec cette solution ca reste rapide au niveau des réponses ?

    D'expérience (d'avant la possibilité de la programmation multi-tiers) d'une application écrite avec D3 et BDE la solution Trigger+Table des Numéros de factures fonctionne très bien en multi-utilisateurs (plus de 17 ans de service, moyenne de 20 utilisateurs d'une PMI, mais 3 au max en facturation) les seuls "trous" (car il y en a toujours) sont dus aux utilisateurs qui supprime des factures, c'est donc à eux de gérer ce "trou". Je sais c'est dur ! mais du coup ils évitent et font un avoir .
    Nota. ce même programme est utilisé par 2 autres TPI (Très Petites Entreprise) dans le même secteur d'activité et, sauf erreur de manipulations (facturation automatique à l'intégration des bons de livraison externe au logiciel) tout de passe bien, toutefois comme il y a peu d'utilisateurs en même temps sur la facturation c'est moins sujet à problème de numérotation.
    c'est possible de le voir?
    je pense que meme avec la solution de trigger peux laisser des trous :
    si deux utilisateur click sur creation de factures, si le 1er annul sa facture il va y'avoir un trou
    c'est possible de le gérer ? ou de l'éviter ?



    pour donner un exemple : dans mon progiciel j'ai une Table Commandes qui contient l'en tête de commande (numero de client, adresse de livraison, date, mode de réglement etc...) une table Lignes de Commandes qui contient les articles commandés (article, prix_unitaire, qte, remise etc...). Une facture (numero de client, date, etc...) est stockée dans le fichier FACTURES et le détail de ces factures, les lignes dans un autre fichier, LIGNES_FACTURES (numero de ligne, commande, article,quantité, pu, remise, n°livraison etc..) une facture peut donc contenir plusieurs commandes, plusieurs livraison sur une même commande etc...
    tu a tus l'analyse de la bd ?


    Pour ce qui est de l'utilisation de autoincfields de Firedac, il me semble que votre colonne ORDERID (OrderID:F2017001) n'est pas numérique donc, cela ne peut pas fonctionner
    non il est numérique pour le F j'envisage de l'ajouter une fois le problème de l'incrément est régler

  11. #11
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 030
    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 030
    Points : 40 928
    Points
    40 928
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par mrsimo7 Voir le message
    tu était dans quelle ville et quelle années ?
    Casablanca mais c'était dans un autre temps où les PC n'étaient pas encore très démocratisés, à l'époque je travaillais sur un IBM36 (le premier du Maroc) et passait même pour un Expert c'était dans la fin des années 80, 85-90 je crois

    avec cette solution ca reste rapide au niveau des réponses ?
    le trigger ou la méthode du DataSnap, mais dans les 2 cas oui

    c'est possible de le voir?
    il fonctionnait chez un de nos sous-traitant de Casablanca il y a encore peu de temps mais l'entreprise a déposé le bilan. Mais c'est loin d'être une simple application de facturation, c'est une application de gestion de production complète (allant de la gestions matières premières au stocks de produits finis en passant par la fabrication, les commandes et facturation clients) dans le domaine de la mode, plus particulièrement la chaussure mais ce que l'on peut faire pour la chaussure s'applique très facilement au textile (l'inverse n'est pas forcément vrai). Ce qui veut dire gestion des coloris et pointures en plus d'une gestion classique de produit et là, autant on trouve beaucoup d'ERP pour de simples produits autant ces ERP ne sont pas adaptés (sauf à créer un article pour chaque couleur et chaque pointure. Sachant qu'un modèle est décliné en moyenne en 10 couleurs (je fais grâce de la matière principale) qu'une moyenne de 14 tailles existe que chaque saison (2 fois par an) on a une trentaine minimum de nouveau modéles : avec un ERP classique cela fait 30*10*14 article à créer !

    je pense que meme avec la solution de trigger peux laisser des trous :
    si deux utilisateur click sur creation de factures, si le 1er annul sa facture il va y'avoir un trou
    c'est possible de le gérer ? ou de l'éviter ?
    comme je l'ai indiqué, si un utilisateur annule (action de destruction) une facture non le trou est inévitable, par contre s'il s'agit de deux demandes de création dont une est annulée tout dépend de la manière dont c'est codé ! pour mémoire le CacheUpdate existe, les FdMemtables voire des Global Temporary table de Firebird aussi.
    Autrement pour gérer les trous (du moins le rapporter de façon à les gérer il y a du SQL pour ça )


    tu a tus l'analyse de la bd ?
    Bien sûr puisque j'en suis le créateur et le seul développeur du projet. Cependant cette analyse n'est pas forcément utilisable dans ton contexte et de plus n'est pas open source. Enfin dernier point cette base de données est sur le point de devenir obsolète, je la trouve mal construite avec les nouveautés et mon expérience actuelle il y a mieux à faire, et je suis en train de mettre au point la structure d'une nouvelle base pour modifier tout le logiciel

    non il est numérique pour le F j'envisage de l'ajouter une fois le problème de l'incrément est régler
    ce n'est pas évident au vu des informations fournies
    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

  12. #12
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2016
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2016
    Messages : 71
    Points : 19
    Points
    19
    Par défaut
    Merci infiniment.

  13. #13
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2016
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2016
    Messages : 71
    Points : 19
    Points
    19
    Par défaut
    Tu as déjà vu ce programme :http://www.ibobjects.com/TechInfo.ht...uditableSeries
    ti_AuditableSeries utilitaire du créateur de http://www.ibobjects.com
    Sinon essaye-le et dis-moi stp ce que tu en penses.

  14. #14
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 030
    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 030
    Points : 40 928
    Points
    40 928
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    je ne vais pas utiliser le logiciel, pas besoin c'est pratiquement ce que j'applique, lire d'abord le test_series.sql m'a suffit, lire le RTF m'a conforté.
    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. Delphi, Firebird et Vista
    Par obione dans le forum Bases de données
    Réponses: 1
    Dernier message: 23/09/2006, 18h02
  2. AutoIncrement Interbase / Firebird
    Par jflebegue dans le forum Débuter
    Réponses: 8
    Dernier message: 28/01/2005, 16h28
  3. Delphi, Firebird, et requetes longues ...
    Par shikami dans le forum Bases de données
    Réponses: 5
    Dernier message: 23/09/2004, 19h04
  4. Delphi, Firebird, et lenteurs
    Par shikami dans le forum SQL
    Réponses: 2
    Dernier message: 22/09/2004, 18h08

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