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

SQL Firebird Discussion :

optimiser une recherche


Sujet :

SQL Firebird

  1. #21
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 021
    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 021
    Points : 40 935
    Points
    40 935
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par Artemus24
    Ce trigger, c'est pour automatiser la recherche du dernier numéro de ticket et de faire un 'ticket <-- ticket +1'.
    Mais pourquoi insérer une nouvelle ligne à chaque fois ?
    pardon mais où est-ce que je fais dans ce trigger une insertion ? le INSERT indiqué ne fait pas d'insertion , c'est lorsqu'il y a INSERT sur la table que le trigger se déclenche

    ce trigger est fait pour
    1- utiliser les séquences (ou générateur) comme clé primaire
    2- faire une numérotation automatique sans trou (du moins je crois) du ticket et ce directement sur le serveur sans intervention de programme
    3- comme la clé primaire est le générateur accéder au dernier enregistrement devient donc facile et rapide

    les SEQUENCE anciennement GENERATEUR sont l'équivalent de l'auto-incrément à la différence près qu'il faut le gérer soit même c'est le but du trigger

    mySQL ....La récupération de la dernière valeur de cet auto incrément est instantanée.
    c'est l'objet de GEN_ID(GEN_VENTE_ID, 0) sans incrément et de GEN_ID(GEN_VENTE_ID, <n>) avec incrément

    @alanglet non, tu ne pinailles pas, je n'ai certainement pas écarté tous les risques, cependant une erreur serait levée à cause de l'index sur NUMEROTICKET (quoique je viens de m'apercevoir que je n'avais pas indiqué qui devait être UNIQUE , tellement cela me semblait évident , je vais faire la correction)

    si Chekkal (ou quelqu'un d'autre) se sent le courage de faire un programme test avec thread (pour simuler plusieurs demandes quasi simultanées à partir d'un même poste) et de le déployer sur plusieurs postes libre à lui, je ne pense pas en avoir le temps ni le courage . Dans l'environnement d'une supérette je ne pense pas que 2 demandes arrivent dans la microseconde cependant !
    @Barbibulle à moins que IBexpert arrive à faire ça aussi ? (peut être pas dans sa version lite quand même )

    la seule solution qui empêcherait les collisions serait une solution multi-tiers (DATASNAP pour les Delphistes) et non client/serveur
    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

  2. #22
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Bonjour SergioMaster,

    Je n'avais pas lu ton trigger, mais à première lecture (je n'ai pas testé) je dirais qu'il y a deux problèmes.

    Problème mineur : Quand la table ventes est vide la première fois.
    Sauf erreur de ma part
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT COALESCE(NUMEROTICKET,0) +1  FROM VENTES WHERE NUMEROVENTE=GEN_ID(GEN_VENTE_ID, 0) INTO NEW.NUMEROTICKET;
    Renvoie un ensemble vide et donc il n'y a pas d'affectation de NEW.NUMEROTICKET

    Et second point plus embêtant :
    Création d'une Vente par INSERT dans la table vente : NUMEROVENTE = 241 => GEN_VENTE=241
    La vente est abandonnée : je fais un ROLLBACK de la Transaction. (donc il n'y a plus d'enregistrement avec NUMEROVENTE = 241 mais le GEN_VENTE est toujours à 241
    La vente suivante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT COALESCE(NUMEROTICKET,0) +1  FROM VENTES WHERE NUMEROVENTE=GEN_ID(GEN_VENTE_ID, 0) INTO NEW.NUMEROTICKET;
    Renvoie un ensemble vide.....et NEW.NUMEROTICKET n'est pas affecté.

    A mon avis la solution la plus simple pour son cas c'est de commencer à mettre un index UNIQUE sur Ticket.
    Puis d'ouvrir une transaction qui va récupérer le dernier ticket utilisé (soit dans une table de ticket soit par "Max(ticket)" soit par "first 1 Order by ticket") et dans cette même transaction faire l'insert dans la table des ventes.
    S'il y a deux ventes simultanées la contrainte d'unicité fera échouer une insertion, il suffit que le programme la rejoue...

  3. #23
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    245
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 245
    Points : 534
    Points
    534
    Par défaut
    Bonjour,

    Ne mélangeons pas les problèmes.
    On peut évidemment prévoir le cas de l'enregistrement du 1er numéro de ticket vide, mais il me semble logique que l'initialisation de cette valeur soit déterminée au début de l'exercice par exemple.
    Quand à la possibilité du rollback ou de l'annulation, c'est à l'exécutable de régler le problème en attribuant le n° lors de l'enregistrement et en empêchant la suppression par les droits d'accès à la table attribués à l'utilisateur ou à son rôle. Mais personne ne pourra empêché le SYSDBA de supprimer un enregistrement.
    Je ne pense cependant pas qu'il soit nécessaire d'aller jusqu'au DATASNAP pour empêcher les collisions.
    La solution avec la table parametres est à mon avis tout à fait utilisable, mais à condition d'être exécutée dans une transaction qui garantit qu'un seul utilisateur peut lire et modifier l'enregistrement à un instant donné.
    Firebird autorise l'exécution d'une transaction dite "SERIALIZABLE" dans laquelle une transaction ne peut commencer que si la précédente est terminée. Voir l'article de Pierre Yager http://www.ibphoenix.com/resources/d...ticles/doc_369
    Comme ce niveau de transaction n'est probablement pas celui utilisé dans le reste de l'application, il est exclu que la mise à jour de la table parametres soit exécutée par un trigger.
    En supposant une table parametres définie ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CREATE TABLE PARAMETRES (
        ID   INTEGER NOT NULL,
        VAL  INTEGER
    );
    ALTER TABLE PARAMETRES ADD CONSTRAINT PK_PARAMETRES PRIMARY KEY (ID);
    La requête suivante exécutée à l'intérieur d'une transaction SERIALIZABLE ouverte juste avant et fermée juste après retourne un numéro unique sans trou dans la série id:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    update parametres
    set val=(select val+1 from parametres where id=:id)
    where id=:id
    returning val
    André

    Edit: J'y suis allé sans doute un peu trop fort avec la transaction SERIALIZABLE car si j'ai bien compris une telle transaction ne pourra pas démarrer si toutes les autres ne sont pas fermées. Un lock_write serait suffisant.

  4. #24
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 021
    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 021
    Points : 40 935
    Points
    40 935
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par Barbibulle Voir le message
    B
    Problème mineur : Quand la table ventes est vide la première fois.
    ... Renvoie un ensemble vide et donc il n'y a pas d'affectation de NEW.NUMEROTICKET
    Tu n'as pas lu le correctif ? en fait je me suis aperçu de ce problème en faisant le test , la proposition à la suite (un IF THEN ) le corrige
    Et second point plus embêtant :
    Création d'une Vente par INSERT dans la table vente : NUMEROVENTE = 241 => GEN_VENTE=241
    La vente est abandonnée : je fais un ROLLBACK de la Transaction. (donc il n'y a plus d'enregistrement avec NUMEROVENTE = 241)
    Je n'ai pas pensé à ce cas effectivement (nul n'est parfait)
    A mon avis la solution la plus simple pour son cas c'est de commencer à mettre un index UNIQUE sur Ticket.
    ça, je le soutiens
    Puis d'ouvrir une transaction qui va récupérer le dernier ticket utilisé (soit dans une table de ticket soit par "Max(ticket)" soit par "first 1 Order by ticket") et dans cette même transaction faire l'insert dans la table des ventes.
    l'objectif était aussi d'éviter le max et mais aussi le first d'où l'utilisation de la séquence pour récupérer la valeur
    en cas de suppression de la transaction un SELECT first avec ORDER BY descendant serait bien évidement mieux , peut être un matînage des deux solutions
    : cas le plus courant le Select = ne renvoi pas null on obtient le numéro suivant (ce que j'ai écrit) si le résultat est null on modifie mon addenda ,on lance UN select first 1 etc.. et si le résultat est encore null (table vide) alors la valeur est 1

    S'il y a deux ventes simultanées la contrainte d'unicité fera échouer une insertion, il suffit que le programme la rejoue...
    c'est évident

    @alanglet que j'ai lu après écriture de ce post (ouvert puis laissé à l'abandon pour le repas et oublié) en fait l'utilisation d'une table paramètre est ce que j'utilise dans mes applications,
    la tentative de trigger était un moyen de contourner/ apporter une solution sur une base existante sans (trop) modifier l'application existante (enlever ce fameux select max et ces ouverture/fermetures de base)
    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

  5. #25
    Membre expert

    Homme Profil pro
    Consultant spécialité Firebird
    Inscrit en
    Mai 2002
    Messages
    2 342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Consultant spécialité Firebird
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 342
    Points : 3 712
    Points
    3 712
    Par défaut
    Citation Envoyé par alanglet Voir le message
    Avec Firebird ceci devrait pouvoir être fait dans une transaction particulière ayant les options:
    LockRead
    LockWrite
    Wait pour attendre que la table soit libérée si un autre utilisateur fait la même manip (très courte).
    et ou en utilisant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ELECT output-specification FROM table-name
      [WHERE search-condition]
      [FOR UPDATE [OF col1 [, col2 [,...]]]]
      WITH LOCK;
    http://www.firebirdsql.org/file/docu...pd25-with-lock

    mais vous pouvez aussi aller lire http://octobinz.developpez.com/artic...e/generateurs/
    ça vous donnera des idées
    Philippe Makowski
    IBPhoenix - Firebird
    Membre de l'April

  6. #26
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2010
    Messages
    944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2010
    Messages : 944
    Points : 123
    Points
    123
    Par défaut
    Je vous remercie tous pour vos réponse, mais j'ai solutionné le problème autrement. J'ai modifié la méthode de codification du N°ticket de cette manière,

    N°ticket:=code opérateur+date+heure

    Code opérateur: est le numéro donné à l’opérateur de saisie pour s'identifier.
    Date:on récupéra le jour+mois+année est on les convertit en entier
    Date:on recupera l' heure+minute+seconde est on les convertit en entier

    qui peut donner par exple:10030102015173615

  7. #27
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 346
    Points : 18 958
    Points
    18 958
    Par défaut
    Salut à tous.

    Citation Envoyé par SergioMaster
    pardon mais où est-ce que je fais dans ce trigger une insertion ? le INSERT indiqué ne fait pas d'insertion , c'est lorsqu'il y a INSERT sur la table que le trigger se déclenche
    Je ne suis pas toujours très clair dans mes explications et je m'en excuse.

    1) quand chekkal fait ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select max(ticket) from vente
    C'est pour récupérer le dernier numéro du ticket de la table 'vente', mais au niveau du langage de programmation.

    2) quand je dis :
    Citation Envoyé par Artemus24
    Mais pourquoi insérer une nouvelle ligne à chaque fois ?
    je m'attendais à une procédure stockée qui donne la valeur du dernier ticket, voire même, en faisant ticket <-- ticket +1.
    Pourquoi ? Pour que le développeur, entre autre chekkal, puisse gérer cette nouvelle valeur à sa guise, mais au niveau de la programmation.

    Or la solution que tu proposes, et qui fonctionne, ne répond pas à la demande de chekkal.
    Tout se passe en interne dans la table vente, par l'intermédiaire du trigger et il ne peut pas récupérer la dernière valeur de ce ticket.
    Chekkal doit, pour récupérer la valeur du ticket, faire un 'select max(ticket) from vente'.

    Est-ce que je suis un peu plus clair sur mes explications ?

    Citation Envoyé par SergioMaster
    les SEQUENCE anciennement GENERATEUR sont l'équivalent de l'auto-incrément à la différence près qu'il faut le gérer soit même c'est le but du trigger
    Grace à toi, j'ai appris comment utiliser les 'GENERATEUR'. Et je t(en remercie.
    Mais je pense que tu t'es compliqué l'existance.

    Voici une solution plus basique et qui correspond à mes explications :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    DROP   DATABASE;
    CREATE DATABASE 'Data\Base.fdb' page_size 4096 DEFAULT CHARACTER SET ISO8859_1;
     
    CREATE TABLE TICKET (
    ID     INTEGER       NOT NULL,
    NUMERO DECIMAL(18,0) NOT NULL);
     
    INSERT INTO TICKET VALUES (1, 0);
     
    UPDATE TICKET SET NUMERO = NUMERO + 1 WHERE ID = 1;
    SELECT * FROM TICKET;
     
              ID                NUMERO
    ============ =====================
               1                     1
     
    UPDATE TICKET SET NUMERO = NUMERO + 1 WHERE ID = 1;
    SELECT * FROM TICKET;
     
              ID                NUMERO
    ============ =====================
               1                     2
     
    COMMIT;
     
    UPDATE TICKET SET NUMERO = NUMERO + 1 WHERE ID = 1;
    SELECT * FROM TICKET;
     
              ID                NUMERO
    ============ =====================
               1                     3
     
    UPDATE TICKET SET NUMERO = NUMERO + 1 WHERE ID = 1;
    SELECT * FROM TICKET;
     
              ID                NUMERO
    ============ =====================
               1                     4
     
    ROLLBACK;
     
    UPDATE TICKET SET NUMERO = NUMERO + 1 WHERE ID = 1;
    SELECT * FROM TICKET;
     
              ID                NUMERO
    ============ =====================
               1                     3
     
    UPDATE TICKET SET NUMERO = NUMERO + 1 WHERE ID = 1;
    SELECT * FROM TICKET;
     
              ID                NUMERO
    ============ =====================
               1                     4
     
     
    exit;
     
    Appuyez sur une touche pour continuer...
    Après on peut faire un habillage en mettant ceci dans une procédure stockée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    DROP   DATABASE;
    CREATE DATABASE 'Data\Base.fdb' page_size 4096 DEFAULT CHARACTER SET ISO8859_1;
     
    CREATE TABLE TICKET (
    ID     INTEGER NOT NULL,
    NUMERO INTEGER NOT NULL);
     
    INSERT INTO TICKET VALUES (1, 0);
     
    SET TERM #;
     
    CREATE PROCEDURE lire
    RETURNS (NUM INTEGER)
    AS
    BEGIN
      FOR SELECT NUMERO FROM TICKET WHERE ID = 1 INTO NUM DO
      BEGIN
        NUM = NUM + 1;
        UPDATE TICKET SET NUMERO = :NUM WHERE ID = 1;
            suspend;
      END
    END#
     
    SET TERM ;#
     
    select num from lire;
     
             NUM
    ============
               1
     
    select num from lire;
     
             NUM
    ============
               2
     
    commit;
     
    select num from lire;
     
             NUM
    ============
               3
     
    select num from lire;
     
             NUM
    ============
               4
     
    rollback;
     
    select num from lire;
     
             NUM
    ============
               3
     
     
    exit;
     
    Appuyez sur une touche pour continuer...
    Citation Envoyé par chekkal
    J'ai modifié la méthode de codification du N°ticket de cette manière : N°ticket:=code opérateur+date+heure
    Sous gros système, au lien de faire un incrément, on utilisait le 'timestamp' qui comprenait la date + l'heure mais avec des millionièmes de secondes.
    Deux insertions consécutives on très peu de chances d'avoir le même identifiant, mais cela arrive parfois.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  8. #28
    Rédacteur/Modérateur

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

    tu oublies que :
    - le INSERT INTO TABLE VALUES peut retourner des valeurs : via la clause RETURNING
    - que tu peux faire un comme dans le trigger proposé SELECT NUMERO FROM TABLE WHERE GENERATEUR=GEN_ID(GEN_VENTE_ID, 0) dans le programme
    ou encore toujours dans le programme récupérer la séquence via SELECT GEN_ID(GEN_VENTE_ID, 0) FROM RDB$DATABASE, il y a foultitude de manière de faire

    je ne me souvenais plus de l'article que nous a indiqué Philippe Makowski merci à lui de me l'avoir remémoré
    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. #29
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 346
    Points : 18 958
    Points
    18 958
    Par défaut
    Salut Sergiomaster.

    A qui s'adresse ton dernier message ?
    Si c'est à moi, je ne comprends pas bien tes explications.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  10. #30
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 021
    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 021
    Points : 40 935
    Points
    40 935
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par Artemus24 Voir le message
    Salut Sergiomaster.

    A qui s'adresse ton dernier message ?
    Si c'est à moi, je ne comprends pas bien tes explications.
    Oui, désolé il était tard et la journée ne s'est pas passée sans quelques problèmes épineux : nouvelles demandes, incidents et poste infecté
    si le premier est normal, le second est quant au troisième on a un représentant un peu trop chaud lapin (avis personnel)

    je m'attendais à une procédure stockée qui donne la valeur du dernier ticket, voire même, en faisant ticket <-- ticket +1.
    une procédure n'est pas nécessaire

    pour revenir plus en détail
    ) quand chekkal fait ceci
    select max(ticket) from vente
    je ferais cela
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT NUMEROTICKET FROM VENTES WHERE NUMEROVENTE=GEN_ID(GEN_VENTE_ID, 0); // peu fiable
    --ou plutôt cela 
    SELECT NUMEROTICKET FROM VENTES ORDER BY NUMEROTICKET DESC ROWS 1  // merci l'index unique
    code cependant que j'aurais déjà pu obtenir lors de mon INSERT
    en utilisant, toujours au niveau "langage programmation"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    INSERT INTO VENTES VALUES (NULL,NULL) RETURNING NUMEROTICKET  // bien sur il y a certainement plus de données à fournir
    [/Mode Delphiste]
    et ceci sans parler :
    -des suites de composants Delphi d'accès aux bases de données qui permettent de gérer les séquences . Je pense par exemple à ZEOSDBO (je n'ai jamais eu la curiosité de voir comment Firedac gérait ça)
    - des transactions encadrant le insert
    etc...
    [/fin Mode]

    Quant à la solution de Checkal (qui est celle couramment utilisée pour les programmes caisses) elle n'a plus rien à voir avec une numérotation suivi sans trou , il s'agit juste de régler un problème d'identifiant unique et à partir du moment le code de l'opérateur (cela aurait pu être de la caisse ou les deux) et le timestamp sont inclus je pense que l'identifiant sera bien unique . A condition que plusieurs caisses ne soient pas ouvertes par le même opérateur
    (c'est du vécu)
    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

  11. #31
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 346
    Points : 18 958
    Points
    18 958
    Par défaut
    Salut SergioMaster.

    Citation Envoyé par SergioMaster
    Quant à la solution de Checkal (qui est celle couramment utilisée pour les programmes caisses) elle n'a plus rien à voir avec une numérotation suivi sans trou , il s'agit juste de régler un problème d'identifiant unique et à partir du moment le code de l'opérateur (cela aurait pu être de la caisse ou les deux) et le timestamp sont inclus je pense que l'identifiant sera bien unique . A condition que plusieurs caisses ne soient pas ouvertes par le même opérateur
    (c'est du vécu)
    Si un problème de cette nature se fait sentir dans une application, genre trop de temps pour obtenir une information, c'est qu'il y a deux problèmes :
    --> soit un problème de conception de la base de données, genre oubli des index ou je ne sais quoi d'autres.
    --> soit un problème fonctionnel mal pensé dès le départ.

    Donc pour identifier une opération de caisse, un numéro séquentiel est une bonne idée, oui mais, à la condition de ne pas avoir 100.000 caissières dans un pays.
    Un numéro séquentiel, OUI, mais pour une et une caissière. Donc il manque d'autres informations pour rendre ce numéro unique.
    Je ne suis pas trop partisan du timestamp qui va occuper trop de place en mémoire, mais plus d'une clef composée dans ce cas là :
    --> matricule ou identifiant de la caissière.
    --> date du jour.
    --> numéro séquentiel dans le jour.

    Et si on a la flemme de chercher le dernier numéro séquentiel, on peut remplacer ce numéro par un 'time'.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. [index] performance sur une recherche descendante
    Par jean-jacques varvenne dans le forum Oracle
    Réponses: 16
    Dernier message: 15/01/2005, 11h22
  2. Optimisation d'une recherche et mise à jour
    Par gandf dans le forum C++Builder
    Réponses: 4
    Dernier message: 07/01/2005, 19h38
  3. Réponses: 8
    Dernier message: 10/09/2004, 18h30
  4. [VB.NET] Quel objet tableau pour une recherche indexée ???
    Par Kitano dans le forum Windows Forms
    Réponses: 7
    Dernier message: 02/09/2004, 10h38
  5. Enlever la surbrillance lors d'une recherche avec vi
    Par sekiryou dans le forum Applications et environnements graphiques
    Réponses: 8
    Dernier message: 04/03/2004, 14h55

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