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

Firebird Discussion :

Communication entre triggers


Sujet :

Firebird

  1. #1
    Membre éclairé
    Avatar de FOCUS77
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2014
    Messages
    336
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2014
    Messages : 336
    Points : 680
    Points
    680
    Par défaut Communication entre triggers
    Bonsoir à tous

    J'utilise FlameRobin+Firebird pour la conception de mes BDD.
    Est-il possible de déclarer une variable V Char(1), qui joue le rôle d'une booléenne, dans un trigger pour qu'elle soit reconnue par d'autre triggers?
    Si oui comment?

    merci d'avance.

  2. #2
    Rédacteur/Modérateur

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

    une variable V Char(1) dans un trigger , AMHA, NON
    par contre utiliser une variable de contexte, au sein de la session OUI, voir SET_CONTEXTet GET_CONTEXT
    si cela doit agir entre session ne reste que la solution table+colonne
    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

  3. #3
    Membre éclairé
    Avatar de FOCUS77
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2014
    Messages
    336
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2014
    Messages : 336
    Points : 680
    Points
    680
    Par défaut
    Bonsoir,

    Merci pour votre réponse sergio.

    peut être il plus commode de reformuler la question

    * Soit la table VENTES (NUM_VNT,NUM_PRDV) clé double.

    * Une nouvelle vente contient un paquet d'enregistrements caractérisés par un même NUM_VNT.

    * Comment conditionner le trigger afin d'attribuer les valeurs convenables à NUM_VNT?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SET TERM ^ ;
    CREATE TRIGGER NvlEnrg FOR VENTES
    ACTIVE BEFORE INSERT POSITION 0
    AS 
    BEGIN
    <Condition1> //le premier enregistrement du paquet.
    new.NUM_VNT=gen_id(AUTOINC,1);
     
    <Condition2> //les autres enregistrements
    new.NUM_VNT=gen_id(AUTOINC,0);
    END^
    SET TERM ; ^
    merci encore.

  4. #4
    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 381
    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 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut Focus77.

    Je ne comprends pas ce que vous essayez de faire.

    Je vais devoir interpréter votre demande.

    Suite à une nouvelle vente, vous recevez un paquet d'enregistrements qui ont tous le même numéro de vente.
    Vous désirez les introduire dans votre table et vous ne savez pas comment le faire car vous risquez d'avoir des doublons.

    A quoi sert votre seconde colonne "NUM_PRDV" ? Je pense qu'elle signifie "numéro du produit de la vente" ?
    C'est colonne qui va servir à distinguer tous vos enregistrements, en lui attribuant un numéro séquentiel.

    Admettons que dans votre paquet d'enregistrements, vous avez cinq enregistrements et que le NUM_VNT = "123456".
    Vous devez entrer votre paquet d'enregistrements de la façon suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    +-----------+-----------+
    |  NUM_VNT  |  NUM_PRDV |
    +-----------+-----------+
    |   123456  |     1     |
    |   123456  |     2     |
    |   123456  |     3     |
    |   123456  |     4     |
    |   123456  |     5     |
    +-----------+-----------+
    Ainsi en incrémentant la colonne NUM_PRDV, vous n'aurez pas de doublons au niveau de la clef primaire de votre table.

    Voici un exemple, basée sur la clef primaire (id ; num). La colonne num sera incrémenté de +1 pour chaque id identifique.

    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
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    CREATE DATABASE '..\Data\Base.fdb' page_size 4096 DEFAULT CHARACTER SET ISO8859_1;
     
    -- =====================
    -- création table "test"
    -- =====================
     
    create table test (
    id    integer   not null,
    num   integer   not null,
    nom   char(25)  not null collate fr_fr,
    primary key (id, num)
    );
     
    -- ===========================
    -- création tigger 'increment'
    -- ===========================
     
    SET TERM #;
     
    CREATE TRIGGER increment for test
    active before insert position 0
    as
    begin
      new.num = (select coalesce(max(num)+1, 1) from test where id = new.id);
    END#
     
    SET TERM ;#
     
    -- =====================
    -- insertion dans 'test'
    -- =====================
     
    insert into test (id,nom) values ( 1,'Un');
    insert into test (id,nom) values (10,'dix');
    insert into test (id,nom) values (20,'vingt');
    insert into test (id,nom) values ( 1,'Deux');
    insert into test (id,nom) values (10,'onze');
    insert into test (id,nom) values (20,'vingt-et-un');
    insert into test (id,nom) values ( 1,'Trois');
    insert into test (id,nom) values (10,'douze');
    insert into test (id,nom) values (20,'vingt-deux');
    insert into test (id,nom) values ( 1,'Quatre');
    insert into test (id,nom) values (10,'treize');
    insert into test (id,nom) values (20,'vingt-trois');
    insert into test (id,nom) values ( 1,'Cinq');
    insert into test (id,nom) values (20,'vingt-quatre');
    insert into test (id,nom) values (20,'vingt-cinq');
     
    -- ================
    -- Vidage de 'test'
    -- ================
     
    select * from test order by id, num;
     
              ID          NUM NOM
    ============ ============ =========================
               1            1 Un
               1            2 Deux
               1            3 Trois
               1            4 Quatre
               1            5 Cinq
              10            1 dix
              10            2 onze
              10            3 douze
              10            4 treize
              20            1 vingt
              20            2 vingt-et-un
              20            3 vingt-deux
              20            4 vingt-trois
              20            5 vingt-quatre
              20            6 vingt-cinq
     
     
    exit;
     
    Appuyez sur une touche pour continuer...
    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  5. #5
    Membre éclairé
    Avatar de FOCUS77
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2014
    Messages
    336
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2014
    Messages : 336
    Points : 680
    Points
    680
    Par défaut
    Bonjour Artemus24

    et merci pour votre aide.

    En fait j'ai travaillé avec les tables à clé double voire triples pendant des années je n'ai de problème à définir ces clés, mais uniquement

    avec les applications mono-postes!!

    Dans une tentative de généraliser le fonctionnement d'une application Mono à une Multi-postes, j'ai réussi à insérer des nouvel enregistrements

    dans des tables à clé primaire unique en utilisant un GENERATOR et un TRIGGER afin d’éviter les doublons (toujours en mode réseau)

    cependant pour la tables à clé double j'ai échoué.

    merci beaucoup.

  6. #6
    Rédacteur/Modérateur

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

    c'est vrai que l'interprétation de la demande peut être divergente. Pour moi, je vois les choses ainsi

    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
    CREATE TABLE VENTES2
    (
      ID Numeric(18,0) NOT NULL,
      PRODUIT Char(6) NOT NULL,
      CONSTRAINT PK_VENTES2 PRIMARY KEY (ID,PRODUIT)
    );
     
    CREATE GENERATOR GEN_VENTES2_ID;
     
    SET TERM ^ ;
    CREATE TRIGGER VENTES2_BI0 FOR VENTES2 
    ACTIVE
    BEFORE INSERT POSITION 0
    AS 
    DECLARE VARIABLE TMP NUMERIC(18,0);
    BEGIN 
      TMP=RDB$GET_CONTEXT('USER_SESSION','NUMVENTE');
      IF (TMP=0) THEN BEGIN
        NEW.ID=NEXT VALUE FOR GEN_VENTES2_ID;
        RDB$SET_CONTEXT('USER_SESSION','NUMVENTE',NEW.ID);
      END
      ELSE NEW.ID=TMP;    
    END^
    SET TERM ; ^
     
    COMMIT;
    le "paquet" d'insertion
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SELECT RDB$SET_CONTEXT('USER_SESSION','NUMVENTE',0) FROM RDB$DATABASE;
    INSERT INTO VENTES2(PRODUIT) VALUES ('A');
    INSERT INTO VENTES2(PRODUIT) VALUES ('B');
    INSERT INTO VENTES2(PRODUIT) VALUES ('C');
    INSERT INTO VENTES2(PRODUIT) VALUES ('D');
    INSERT INTO VENTES2(PRODUIT) VALUES ('E');
    INSERT INTO VENTES2(PRODUIT) VALUES ('F');
    INSERT INTO VENTES2(PRODUIT) VALUES ('G');
    INSERT INTO VENTES2(PRODUIT) VALUES ('H');
    Citation Envoyé par FOCUS77
    avec les tables à clé double voire triples pendant des années je n'ai de problème à définir ces clés,
    oui mais une bonne clé primaire numérique auto-incrémentée c'est quand même bien mieux, quitte à avoir ensuite des index unique avec plusieurs champs, mais ce n'est pas le sujet.
    Citation Envoyé par Artemus24
    Je vais devoir interpréter votre demande.
    mauvaise interprétation AMHA car dans le trigger abordé , seul un champ est modifié

    P.S. en aparté @artemus24 je n'aime vraiment pas cette manie de toute la discussion, ce ne devrait être réservé qu'à la/les solutions trouvées pertinentes
    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

  7. #7
    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,

    Il ne faut pas forcément vouloir tout faire avec des triggers. Ce qui est important en multi-poste c'est d'utiliser les générateurs (et non un trigger).

    Pour une clé "simple" effectivement un trigger qui utilise un générateur fera l'affaire.

    Dans votre cas, une clé multiple avec un lot d'enregistrement avec une racine commune. C'est au logiciel client (celui qui fait les insert) de piloter cette clé...

    C'est a dire avant la première insertion du lot faire une demande au serveur d'une nouvelle valeur du générateur de NUM_VNT. Et utiliser cette valeur pour le lot d'insertion.

    Et quand à NUM_PRDV si c'est juste un compteur qui démarre de 1 (ou 0) à chaque nouvelle Vente vous pouvez également le gérer par le programme.

    Tout simplement.

  8. #8
    Membre éclairé
    Avatar de FOCUS77
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2014
    Messages
    336
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2014
    Messages : 336
    Points : 680
    Points
    680
    Par défaut
    @ SergioMaster

    Merci pour votre code efficace et qui m'a appris de nouvelles choses si importantes!

    @ Barbibulle

    NUM_PRDV désigne le code unique d'un produit.

    Merci pour votre méthode, seulement je crois que pour fonctionner correctement on doit créer une table 'maitresse' (le truc que cherche à éviter)

    pour piloter ces paquets d'enregistrements, sinon ils peuvent tomber en conflit.

    Je déclare cette discussion comme résolue.

    merci beaucoup

  9. #9
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    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 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par FOCUS77 Voir le message
    @ SergioMaster
    Merci pour votre code efficace et qui m'a appris de nouvelles choses si importantes!
    C'est donc cette réponse qu'il aurait fallu
    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
    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 381
    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 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut à tous.

    Citation Envoyé par Sergiomaster
    mauvaise interprétation AMHA car dans le trigger abordé , seul un champ est modifié
    Dans ma solution aussi. Le trigger gère la colonne 'NUM' afin de rendre la clef primaire (id ; num) unique.

    En fait, j'ai raisonné à l'envers de toi. J'ai compris qu'il connaissait la valeur de 'NUM_VNT', mais qu'il ne savait pas gérer les doublons dans la table 'VENTE'.
    J'ai utilisé le trigger pour résoudre le problème de l'unicité de la clef primaire, qui selon moi, est bien un problème technique et non fonctionnel.

    J'ai testé ta solution. Je suis désolé de le dire mais je ne comprends pas du tout l'intérêt de procéder ainsi.
    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
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    -- =============
    -- Table 'vente'
    -- =============
     
    create table vente
    (
      id      numeric(18,0) not null,
      produit char(6)       not null,
      primary key (id, produit)
    );
     
    -- ==================
    -- Création Generator
    -- ==================
     
    create generator gen_vente;
     
    -- ================
    -- Création Trigger
    -- ================
     
    set term $$ ;
     
    create trigger vente_trig
    for vente active
    before insert position 0
    as
    declare variable tmp numeric(10,0);
    begin
      tmp = rdb$get_context('USER_SESSION','NUMVENTE');
     
      if (tmp=0) then
      begin
        new.id = next value for gen_vente;
     
        rdb$set_context('USER_SESSION','NUMVENTE',new.id);
      end
      else new.id = tmp;
    end$$
     
    set term ; $$
     
    -- ==============
    -- Initialisation
    -- ==============
     
    select rdb$set_context('USER_SESSION','NUMVENTE',0) FROM rdb$database;
     
    RDB$SET_CONTEXT
    ===============
                  0
     
     
    -- ===========
    -- Jeu d'essai
    -- ===========
     
    insert into vente(produit) values ('A');
    insert into vente(produit) values ('B');
    insert into vente(produit) values ('C');
    insert into vente(produit) values ('D');
    insert into vente(produit) values ('E');
    insert into vente(produit) values ('F');
    insert into vente(produit) values ('G');
    insert into vente(produit) values ('H');
    insert into vente(produit) values ('I');
    insert into vente(produit) values ('J');
    insert into vente(produit) values ('K');
    insert into vente(produit) values ('L');
    insert into vente(produit) values ('M');
    insert into vente(produit) values ('N');
    insert into vente(produit) values ('O');
    insert into vente(produit) values ('P');
    insert into vente(produit) values ('Q');
    insert into vente(produit) values ('R');
    insert into vente(produit) values ('S');
    insert into vente(produit) values ('T');
    insert into vente(produit) values ('U');
    insert into vente(produit) values ('V');
    insert into vente(produit) values ('W');
    insert into vente(produit) values ('X');
    insert into vente(produit) values ('Y');
    insert into vente(produit) values ('Z');
     
    select * from vente;
     
                       ID PRODUIT
    ===================== =======
                        1 A
                        1 B
                        1 C
                        1 D
                        1 E
                        1 F
                        1 G
                        1 H
                        1 I
                        1 J
                        1 K
                        1 L
                        1 M
                        1 N
                        1 O
                        1 P
                        1 Q
                        1 R
                        1 S
                        1 T
     
                       ID PRODUIT
    ===================== =======
                        1 U
                        1 V
                        1 W
                        1 X
                        1 Y
                        1 Z
     
     
    exit;
     
    Appuyez sur une touche pour continuer...
    Si j'ai bien compris le fonctionnement de ton code, tu crées une variable de nom 'NUMVENTE' qui est associé à la session de l'utilisateur.

    1) Qu'est-ce qui se passe si tu changes de session ?
    A priori, je pense que la variable 'NUMVENTE' est local à la session de l'utilisateur et non global à tous les utilisateurs.
    Chaque session va gérer la variable d'une manière indépendante.
    Tu peux très bien avoir la valeur x pour l'utilisateur 'toto', et la même valeur pour l'utilisateur 'titi'.

    Or d'après ce que j'ai compris, la colonne 'id' demande que cette valeur soit unique pour un utilisateur donné.
    Ou alors, il manque un bout de code qui pourrait garantir cette unicité. En fait, j'ai pas compris l'utilité de cette astuce.

    2) Cette astuce va créer une variable qui sera stockée dans FireBird. Est-ce bien cela ? C'est-à-dire stocké dans la mémoire de FireBird.
    Qu'est-ce qui se passe si FireBird plante ? Je pense que tu perds le contenu de toutes ces variables.
    Je crois qu'en procédant ainsi, tu crées un problème d'intégrité !

    Dans ce cas, il vaudrait mieux créer une table paramètre, en associant l'utilisateur à cette variable NUMVENTE.

    3) quand on gère une base de données, on fait en sorte de stocker toutes les valeurs importante dans des tables et non dans des variables mémoires du SGBD.
    Le but d'une modèle conceptuel de données est justement de résoudre ce genre de problème.
    Et de définir le rôle que chaque attribut des entités va jouer au sein de cette base.

    C'est pourquoi dans la plupart des SGBD, il est impossible de stocker des variables soit dans la session, soit dans la mémoire du SGBD.
    En général, une table en mémoire est destinée à accélérer les performances.

    Citation Envoyé par FOCUS77
    Une nouvelle vente contient un paquet d'enregistrements caractérisés par un même NUM_VNT.
    Comment conditionner le trigger afin d'attribuer les valeurs convenables à NUM_VNT?
    C'est cette phrase que je n'ai pas comprise.
    En lisant votre paquet d'enregistrements, est-ce que vous récupérez bien la valeur de votre "NUM_VNT" ?
    Comme je suppose que la réponse est OUI, je ne comprends pas la nature de votre problème !

    En admettant que cette information soit uniquement renseigné sur le premier enregistrement de votre paquet, c'est dans votre application que vous devez gérer la propagation de cette valeur, lors de vos insertions dans la table vente.

    D'où ma question : quelle est la difficulté qui vous empêche de récupérer ce "NUM_VNT" pour venir l'insérer dans votre table "VENTES" ?

    Normalement, un trigger n'est pas destiné à résoudre ce genre de problème et dans votre cas, il s'agit bien d'un problème applicatif.

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

  11. #11
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    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 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour,
    Citation Envoyé par Artemus24 Voir le message
    J'ai compris qu'il connaissait la valeur de 'NUM_VNT',
    le "cahier des charges" (le post 2 et le titre de la discussion quoique pas très explicite) parle de bien de NUM_VENT (id dans mon code)
    J'ai testé ta solution. Je suis désolé de le dire mais je ne comprends pas du tout l'intérêt de procéder ainsi.
    tu ne l'a pas forcément testé correctement avec isql car tu remarqueras que le bloc contient le set_context à 0, si tu répetes plusieurs fois ce bloc tu verras que ID=NUM_VENT change
    Si j'ai bien compris le fonctionnement de ton code, tu crées une variable de nom 'NUMVENTE' qui est associé à la session de l'utilisateur.
    OUI
    1) Qu'est-ce qui se passe si tu changes de session ?
    c'est le principe de la variable de contexte, elle disparait
    A priori, je pense que la variable 'NUMVENTE' est local à la session de l'utilisateur et non global à tous les utilisateurs.
    Chaque session va gérer la variable d'une manière indépendante.
    oui
    Tu peux très bien avoir la valeur x pour l'utilisateur 'toto', et la même valeur pour l'utilisateur 'titi'.
    non, car dans le trigger, NUMVENT=la SEQUENCE (le générateur)
    la variable de contexte est réinitailisée à chaque lancement du Script (paquet) d'insertion.
    J'aurais peut être pu mettre EXECUTE BLOCK AS BEGIN <sql paquet> END pour bien le faire comprendre mais pour moi, quand je pense script, je pense toutes instructions ensemble

    Dans ce cas, il vaudrait mieux créer une table paramètre, en associant l'utilisateur à cette variable NUMVENTE.
    ma première réponse proposait l'utilisation d'une variable de contexte OU une table, mais voilà :
    Citation Envoyé par FOCUS77
    pour fonctionner correctement on doit créer une table 'maitresse' (le truc que cherche à éviter)
    le "cahier des charges" est explicite

    3) quand on gère une base de données, on fait en sorte de stocker toutes les valeurs importante dans des tables et non dans des variables mémoires du SGBD.
    Le but d'une modèle conceptuel de données est justement de résoudre ce genre de problème.
    Et de définir le rôle que chaque attribut des entités va jouer au sein de cette base.
    ...
    il s'agit bien d'un problème applicatif.
    on est d'accord, Barbibulle l'a d'ailleurs fait remarquer , comprenons nous bien : je répond à un problème posé, je ne corrige pas la logique du modèle (criticable) ni de l'applicatif.

    C'est pourquoi dans la plupart des SGBD, il est impossible de stocker des variables soit dans la session, soit dans la mémoire du SGBD.
    affirmation que j'aurais du mal à confirmer ne maitrisant que peu de SGBD, tout ce que je peux dire c'est que SQLITE le peut et que, selon la documentation (obtenu avec les mots clés <SGBD>+Variable de contexte) que j'ai lu MS SQL Server et Oracle aussi

    C'est cette phrase que je n'ai pas comprise.
    En lisant votre paquet d'enregistrements, est-ce que vous récupérez bien la valeur de votre "NUM_VNT" ?
    Comme je suppose que la réponse est OUI, je ne comprends pas la nature de votre problème !
    Justement, moi je l'ai interprété comme NON
    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
    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 381
    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 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut SergioMaster.

    Je suis peut-être pinailleur, mais j'ai besoin de comprendre deux choses :
    --> la formulation de la demande faite par FOCUS77. Sur ce point, sa demande n'est pas clair.
    --> trouver une solution qui correspond à la bonne pratique et non une bidouille.

    Je reprends les différentes points de FOCUS77.
    1) le titre de ce sujet:
    Citation Envoyé par Focus77
    Discussion: Communication entre triggers
    A priori, chaque trigger est indépendant les uns des autres. En réponse, je dirais qu'il déconseillé d'agir ainsi.

    2) sa demande :
    Citation Envoyé par Focus77
    Est-il possible de déclarer une variable V Char(1), qui joue le rôle d'une booléenne, dans un trigger pour qu'elle soit reconnue par d'autre triggers?
    Pourquoi parle-t-il d'un booléen ? Et pour quel usage ?

    3) autre formulation de sa demande. Je constate qu'entre son premier poste et le suivant, ce sont deux demandes différentes.
    Citation Envoyé par Focus77
    Soit la table VENTES (NUM_VNT,NUM_PRDV) clé double.
    J'ai cru comprendre un problème de remplissag de sa clé double.

    Citation Envoyé par Focus77
    * Une nouvelle vente contient un paquet d'enregistrements caractérisés par un même NUM_VNT.
    Je suppose qu'il peut récupérer ce 'NUM_VNT' depuis son paquet d'entregistements.

    Citation Envoyé par Focus77
    * Comment conditionner le trigger afin d'attribuer les valeurs convenables à NUM_VNT?
    J'ai beau tourné le problème dans tous les sens, je ne comprends pas où se trouve la difficulté.
    C'est quoi la contrainte ? C'est pas avec le peu d'information qu'il nous communique que nous allons comprendre sa problématique.

    4) il donne quelque explication :
    Citation Envoyé par Focus77
    <Condition1> //le premier enregistrement du paquet.
    new.NUM_VNT=gen_id(AUTOINC,1);
    Il y a une condition (laquelle ?) qui permet d'initialiser ne contenu de 'NUM_NVT' avec la valeur 1.

    Citation Envoyé par Focus77
    <Condition2> //les autres enregistrements
    new.NUM_VNT=gen_id(AUTOINC,0);
    Il y a une autre condition (laquelle ?) qui permet d'initialiser cette fois-ci le contenu de 'NUM_NVT' avec la valeur 0.

    Déjà pourquoi mettre 1 ou 0, alors que le "gen_id()" a pour usage de gérer un auto increment ?
    Est-ce qu'il a besoin de réinitialiser son incrément (c'est ce que j'ai cru comprendre, gérer une rupture de séquence) ?
    C'est sur cette idée que j'ai donné ma solution (mon premier message).
    Après tout il parle bien d'une clef double, non ?
    Dans mon exemple, la clef double est (id ; num) et c'est sûr 'num' que je procède à l'incrément avec rupture de séquence sur 'id'.

    5) ensuite, dans son troisième message, il précise :
    Citation Envoyé par Focus77
    mais uniquement avec les applications mono-postes!!
    Quel est le rapport avec son problème ?
    Cela fait plus de 20 ans que les micro-ordinateurs ne sont plus mono-poste comme il le dit.
    On parle plutôt d'ordinateurs multithreading, c'est-à-dire multi-coeurs et multi-tâches.

    Citation Envoyé par Focus77
    Dans une tentative de généraliser le fonctionnement d'une application Mono à une Multi-postes, j'ai réussi à insérer des nouvel enregistrements
    dans des tables à clé primaire unique en utilisant un GENERATOR et un TRIGGER afin d’éviter les doublons (toujours en mode réseau)
    cependant pour la tables à clé double j'ai échoué.
    Là, c'est complètement obscure, car je ne comprends pas la problématique.
    S'il a besoin d'être le seul à écrire dans sa table à un instant donné, il suffit de mettre en place un verrou (lock table).
    Ainsi deux accès en parallèle à la table, seront sérialisés par le verrou qui admettra qu'une seule personne en écriture.

    Et à ma grande surprise, la solution que tu proposes ne résoud pas les accès concurrents à la table.

    6) voici quelques réponses de Barbibulle :
    Citation Envoyé par Focus77
    Ce qui est important en multi-poste c'est d'utiliser les générateurs (et non un trigger).
    Oui et non. La sérialisation du traitement nécessite d'avoir à un instant donné ce que l'on nomme un MUTEX en programmation parallèle.
    C'est-à-dire en accès concurentiel, être le seul à effectué une opération critique.

    Oui, je suis d'accord de faire cet incrémentation avec un generator.
    Non, car il faut être seul pour l'accès à la table. Ce qui nécessite le verrou (lock).

    Citation Envoyé par Focus77
    C'est au logiciel client (celui qui fait les insert) de piloter cette clé...
    Il a été le premier à le dire, et je confirme qu'il a raison.
    Il y a plus de possibilité de gestion de cet incrément dans un langage de programmation que de le faire en FireBird.
    Vu que c'est un problème technique, on peut quand même trouver une solution en FireBird.

    Citation Envoyé par Focus77
    Et quand à NUM_PRDV si c'est juste un compteur qui démarre de 1 (ou 0) à chaque nouvelle Vente vous pouvez également le gérer par le programme.
    C'est exactement la solution que j'ai proposé.
    La colonne 'NUM_VNT' est l'information qu'il récupère de son paquet d'enregistrements.
    Dans toutes les lignes qu'il va insérer dans la table, pour ce paquet d'enregistrements, cette colonne aura toujours la même valeur.

    La colonne 'NUM_PRDV' est l'incrément qu'il va faire varier de 1 à N, où N représente le nombre d'enregistrement dans son paquet.

    Au final, il gère une clef double composé de (NUM_VNT ; NUM_PRDV).

    Et en réponse, il dit :
    Citation Envoyé par Focus77
    NUM_PRDV désigne le code unique d'un produit.
    Et qu'est-ce qui se passe, si dans un paquet, il y a plusieurs fois le même code du produit ?
    Soit sa clef double est mal conçue, soit il nous manque une information capitale.
    Par exemple, la quantité acquise sur un produit donné.

    Et il conclu ceci :
    Citation Envoyé par Focus77
    Je déclare cette discussion comme résolue.
    mais on ignore comment il a résolu son problème.

    Je tiens à préciser quelques points :
    Citation Envoyé par Sergiomaster
    le "cahier des charges" (le post 2 et le titre de la discussion quoique pas très explicite) parle de bien de NUM_VENT (id dans mon code)
    Ton message laisse supposer qu'il connait ce numéro de vente.

    Et un peu plus loin dans le même message, tu dis :
    Citation Envoyé par Sergiomaster
    Justement, moi je l'ai interprété comme NON
    Alors c'est OUI ou c'est NON ?

    Car s'il ignore ce numéro de vente (information à mon avis hyper importante pour retrouver le paquet dans la table), je ne voie pas comment il va faire pour intervenir suite à une réclamation faite par un client.
    A moins que l'accès se fasse sur le numéro client et une date.

    Citation Envoyé par Sergiomaster
    affirmation que j'aurais du mal à confirmer ne maitrisant que peu de SGBD
    En ce qui concerne DB2 sous IBM Z/OS, c'est-à-dire gros système, en mon temps, cela n'existait pas.
    Sous MySql, il est impossible de le faire. Sous FireBird, ce sont les "generator" ou "sequence" et ce que je vient de découvrir avec toi "RDB$SET_CONTEXT('USER_SESSION','NUMVENTE',0);".
    Sous SQL Server, à vrai dire, je n'en sais rien.

    La solution la plus évidente pour gérer ce genre de cas est de créer une table en mémoire (memory ou heap sous mysql) du SGBD.
    A priori, je ne voie pas trop l'intérêt de gérer des variables au niveau du SGBR.

    Même si on peut le faire, la question reste l'autorisation de l'utilisateur sur cette fonctionnalité.
    Quand j'étais administrateur DB2, un utilisateur lamba n'avait que les autorisations suivantes : "select, insert update et delete".
    Ce qui limite grandement tout ce que l'on peut faire avec un SGBD.

    Autre point où tu confirmes ce que je sous-entendais :
    [quote="Sergiomaster"]
    Citation Envoyé par Artemus24
    1) Qu'est-ce qui se passe si tu changes de session ?
    c'est le principe de la variable de contexte, elle disparait[quote]
    Dans l'utilisation de l'incrément, la solution n'est pas de créer une variable de contexte, mais une variable permanente associé à une database.
    Je n'ai pas testé, mais qu'est-ce qui se passe si tu arrêtes ton SGBD et que tu le redémarres. Est-ce que tu perds aussi le contenu de ton "generator" ?

    Arrivé en ce point du sujet, je ne sais toujours pas, avec exactitude quel est la nature du problème rencontré par Focus77.

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

  13. #13
    Rédacteur/Modérateur

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

    En préambule , je vais utiliser le terme de SEQUENCE plutôt que de GENERATEUR pour m'imprégner de ce terme Firebird qui n'existe je crois que depuis la version 2.1, ayant utilisé INTERBASE 5 avant FIREBIRD j'en suis resté au vieux terme et donc essaye d'utiliser ce nouveau terme

    Que FOCUS77 se soit mal exprimé dans son titre, comme dans son exposé du problème dans son entame de discussion c'est évident !
    si on retire cette entame pour se concentrer sur la reformulation (son post suivant ne sert à rien que se défendre sur ce qu'il à pu prendre comme une offense lors de ta première intervention)
    on en revient donc a :
    1- Soit la table VENTES (NUM_VNT,NUM_PRDV) clé double.
    2- Une nouvelle vente contient un paquet d'enregistrements caractérisés par un même NUM_VNT.
    3- Comment conditionner le trigger afin d'attribuer les valeurs convenables à NUM_VNT?
    1 >> l'existant (il y manque le fait qu'une SEQUENCE existe)
    2 >> l'action à faire
    3>> la question

    il est dommage que le point 2 ne soit pas explicité et que la contrainte pas de table supplémentaire ne soit exprimé qu'après
    j'y ai répondu à ma manière tout d'abord avec un DDL puis le "paquet d'enregistrements" tel qu'il devrait être pour pouvoir répondre à la question
    et ce sans "programmation" (après tout c'est un forum sur Firebird)

    Et qu'est-ce qui se passe, si dans un paquet, il y a plusieurs fois le même code du produit ?
    Car s'il ignore ce numéro de vente (information à mon avis hyper importante pour retrouver le paquet dans la table), je ne voie pas comment il va faire pour intervenir suite à une réclamation faite par un client.
    A moins que l'accès se fasse sur le numéro client et une date.
    Où as tu vu une notion de client ou de date ? moi je n'ai lu que : "faire une insertion d'enregistrement en paquets avec un numéro unique NUM_VENT". Tes spéculations ne sont pas dans le "cahier des charges" donc on ignore, c'est son problème pas le nôtre, on peut certes critiquer/indiquer des incohérences
    Ton message laisse supposer qu'il connait ce numéro de vente.
    Non, justement, c'est celui que le trigger va obtenir

    4) il donne quelque explication :
    new.NUM_VNT=gen_id(AUTOINC,1);
    Il y a une condition (laquelle ?) qui permet d'initialiser ne contenu de 'NUM_NVT' avec la valeur 1.
    new.NUM_VNT=gen_id(AUTOINC,0);
    Il y a une autre condition (laquelle ?) qui permet d'initialiser cette fois-ci le contenu de 'NUM_NVT' avec la valeur 0.
    ton erreur d'interprétation vient de là , AUTOINC est un générateur, gen_id l'appel à ce générateur avec dans le premier cas Incrémentation et dans le second pas d'incrément

    La solution proposée
    on ignore comment il a résolu son problème.
    exact mais si la discussion est fermée soit il l'a utilisé soit il est impoli

    la solution que tu proposes ne résout pas les accès concurrents à la table.
    je ne suis pas sur de ma solution à 100% mais quand même, vu que l'on fait appel à une SEQUENCE servant à obtenir un numero unique, sauf si Firebird gère mal les générateurs (depuis le temps cela se saurait) je vois pas la raison de cette critique

    ce qui nous amène au point 6
    on est tous tout à fait d'accord sur l'utilisation d'une SEQUENCE , que ce soit à l'intérieur d'un programme ou via un trigger ne change pas grand chose :
    Dans le programme on utilisera SELECT GEN_ID(AUTOINC,1) FROM RDB$DATABASE et on récupére la valeur dans une variable utilisée par la suite
    c'est en gros ce que fait le trigger que j'ai proposé

    Non, car il faut être seul pour l'accès à la table. Ce qui nécessite le verrou (lock).
    par contre là pas d'accord, à quoi servirait un verrou sur la table ? AMHA à rien, s'il devait y avoir verrou ce serait sur la SEQUENCE (aka générateur) or ce n'est pas l'utilisateur qui y accède mais bien FIREBIRD. Est-ce que tu te poses des questions quand tu utilises le AutoInc de mysql ?

    le seul inconvénient d'une SEQUENCE reste dans les Annulations ou Rollbacks , une SEQUENCE ne revient jamais (sauf de façon explicite bien sur) en arrière
    Je n'ai pas testé, mais qu'est-ce qui se passe si tu arrêtes ton SGBD et que tu le redémarres. Est-ce que tu perds aussi le contenu de ton "generator" ?
    voilà la clé de voute de la "petite polémique" j'ai l'impression que tu n'as pas compris ce qu'est une SEQUENCE pour FIREBIRD et la différence d'avec une variable de contexte. La variable de contexte utilisateur n'existe que le temps de la session contrairement à la SEQUENCE , faisant partie des DDL, et donc de la base de données

    La solution la plus évidente pour gérer ce genre de cas est de créer une table en mémoire (memory ou heap sous mysql) du SGBD.
    qu'est ce que une table en mémoire sinon une table contenant n colonnes (dans notre cas 1) et quel serait la différence d'avec la variable de contexte ? AMHA aucune

    En ce qui concerne DB2 sous IBM Z/OS, c'est-à-dire gros système, en mon temps, cela n'existait pas.
    Sous MySql, il est impossible de le faire.
    MySQL n'est pas forcément une référence et du coup pas impossible avec les tables mémoires et s'il y a possibilité d'accéder a un autoinc (=SEQUENCE)
    pour DB2, cela fait des années que je l'ai plus touchée, j'ai fait beaucoup d'applications (et pas des moindres) sous IBM xx jusqu'à l'arrivée des AS400 et n'ai aucun souvenir de SEQUENCE ni de comment le problème était géré mais c'était une autre époque (l'âge de pierre diront certains)
    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

  14. #14
    Rédacteur/Modérateur

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

    juste en écho à cette discussion, j'ai une veille sur le forum Embarcadero/Firedac et un intervenant vient de poster cette question
    <https://forums.embarcadero.com//forum.jspa?forumID=502>
    or
    <https://forums.embarcadero.com//thread.jspa?threadID=171866>

    For your convenience, the new message is included below:
    --------------------------------------------------------------
    Hi,

    So the question remains :
    Is it possible to create an auto increment field on a secondary composite field using FireDac settings and it will be saved in the DB (Database independent)?

    Don't want to use 'Situation 2' as it not creates incremental fields by group of the details, but by the whole table.

    Mostly I stayed away from auto incremental fields, and let the program create it. It still seems the old way(by code) is preferable.
    For example using the function onNewRecord and a Query named qMax :


    procedure TFTest.qDetailNewRecord(DataSet: TDataSet);
    var mID : Integer;
    begin
    {get master ID}
    mID:= qDetail.FieldByName('MasterID').AsInteger;
    {get detail max ID(if null then return 0)}
    qMax.SQL.Clear;
    qMax.SQL.Add('Select COALESCE(MAX(DetailID),0) as MaxID from Detail');
    qMax.SQL.Add('Where Detail.MasterID = ' + QuotedStr(IntToStr(mID)));
    {set next ID}
    qMax.Open;
    qDetail.FieldByName('DetailID').AsInteger:= qMax.FieldByName('MaxID').AsInteger + 1;
    qMax.Close;
    end;
    Outre le code Delphi, criticable de mon point de vue, c'est la réflexion "je reste en dehors des champs incrémentés, il semble toujours que la vieille méthode (par code) reste préférable" qui m'a amusé.
    En tout cas ceci, AMHA, dans un environnement multi-utilisateurs sans précautions de blocage, est à éviter absolument

    NB. Comme tout le monde ne pourra pas se connecter sur la discussion citée , le 'Situation 2' correspond à une utilisation de champs auto incrémentés
    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

  15. #15
    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 381
    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 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut SergioMaster.

    Citation Envoyé par SergioMaster
    si on retire cette entame pour se concentrer sur la reformulation (son post suivant ne sert à rien que se défendre sur ce qu'il à pu prendre comme une offense lors de ta première intervention)
    De toute évidence, je crois qu'il y a un problème de communication sur le post #5. En quoi l'ai-je offensé ? En rien, vu que je n'ai toujours pas compris les explications données sur ces trois messages.
    Le fait d'aborder la question des mono-postes et de multi-postes (???) obscurcit d'autant plus les explications sur la nature de son problème ?
    Et si quelqu'un doit se sentir offensé, c'est bien moi car après avoir fait l'effort de lui apporter une solution, il la rejette comme si j'ai un imbécile !!!

    Je rappelle que la courtoisie est la moindre des politesse concernant les échanges sur les forums, ainsi que de bien s'exprimer afin d'être compris. Passons !

    Citation Envoyé par SergioMaster
    1 >> l'existant (il y manque le fait qu'une SEQUENCE existe)
    C'est une hypothèse que je ne comprends même pas.
    Si l'information concernant le NUM_VNT est disponible dans son paquet d'enregistrements, en quoi devient-elle indisponible ? Aucune explication. Donc on ne peut émettre que des hypothèses.

    Citation Envoyé par SergioMaster
    il est dommage que le point 2 ne soit pas explicité et que la contrainte pas de table supplémentaire ne soit exprimé qu'après
    En quoi utiliser une table supplémentaire est une solution à son problème, même s'il ne veut pas aborder cette question ? Autre hypothèse sans aucune justification.

    Citation Envoyé par SergioMaster
    pour pouvoir répondre à la question et ce sans "programmation" (après tout c'est un forum sur Firebird)
    J'ai eu la même réaction que toi. J'ai apporté une solution FireBird et non une solution programmation, bien que j'ai abordé cette solution après l'intervention de Barbibulle.

    Citation Envoyé par SergioMaster
    Où as tu vu une notion de client ou de date ?
    Nul part. J'ai emis cette hypothèse.

    Citation Envoyé par SergioMaster
    on peut certes critiquer/indiquer des incohérences
    Mais je ne critique rien du tout, je ne comprends pas ni la demande de Focus77, ni la solution que tu proposes.

    Citation Envoyé par SergioMaster
    Non, justement, c'est celui que le trigger va obtenir
    Mais sur quelle hypothèse tu te bases pour dire cela ?
    Je reprends ce que dit Focus77 :

    Citation Envoyé par Focus77
    Une nouvelle vente contient un paquet d'enregistrements caractérisés par un même NUM_VNT.
    Ce NUM_VNT est bien stocké dans son paquet d'enregistrements, donc il connait sa valeur.

    Citation Envoyé par Focus77
    Comment conditionner le trigger afin d'attribuer les valeurs convenables à NUM_VNT?
    Quand il est dans le trigger, ce NUM_VNT devient une valeur inconnue. D'où le fait qu'il demande à "attribuer les valeurs convenables à NUM_VNT".

    Hypothèse de ma part, ce NUM_VNT est connu sur le premier enregistrement de ce paquet, mais par après.
    Donc la solution est de faire un reconduction de ce NUM_VNT, lors de l'insertion des lignes dans la table.
    En quoi est-il nécessaire de passer par un trigger pour résoudre ce problème applicatif ?

    Citation Envoyé par Focus77
    Non, justement, c'est celui que le trigger va obtenir
    Je ne suis pas d'accord avec toi. Ce NUM_VNT, il est bien obligé de le connaitre puisqu'il est stocké dans le paquet d'enregistrements.
    Il le dit lui même : "un paquet d'enregistrements caractérisés par un même NUM_VNT".
    Désolé de le dire, mais tu fais une erreur d'interprétation.

    Citation Envoyé par SergioMaster
    ton erreur d'interprétation vient de là , AUTOINC est un générateur, gen_id l'appel à ce générateur avec dans le premier cas Incrémentation et dans le second pas d'incrément
    Je te rassure, j'ai bien lu son exemple avec le "genertor". D'où ma question : pourquoi a-t-il besoin de créer ce "generator" ?

    Citation Envoyé par SergioMaster
    je vois pas la raison de cette critique
    Encore une fois, tu te m'eprends sur mes intentions. Je ne critique personne, j'essaye de comprendre.
    C'est Focus77 qui aborde la question dans son post #5, de ces mono-postes et multi-postes.
    J'en ai déduit qu'il a un problème d'accès concurentiel, d'où ma remarque d'utiliser un verrou (with lock) pour bloquer les accès en écriture des autres intervenants.

    Citation Envoyé par SergioMaster
    on est tous tout à fait d'accord sur l'utilisation d'une SEQUENCE , que ce soit à l'intérieur d'un programme ou via un trigger ne change pas grand chose
    Désolé de le dire, mais mon opinion sur ce sujet a évolué.
    Je rejoins l'idée de Barbibulle que la solution est applicative et non dans FireBird. Selon moi, faire un trigger est une erreur.

    Sinon, je te remercie de nous avoir fait découvert cette commande :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    RDB$SET_CONTEXT('USER_SESSION','NUMVENTE',NEW.ID);
    que je ne conaissais pas. Comme je te l'ai dit, je suis là pour apprendre et non pour critiquer comme tu sembles le croire. Donc si je ne comprends pas, je te le fais savoir.

    Citation Envoyé par SergioMaster
    par contre là pas d'accord, à quoi servirait un verrou sur la table ?
    A cause des accès concurentiels !

    Citation Envoyé par SergioMaster
    Est-ce que tu te poses des questions quand tu utilises le AutoInc de mysql ?
    Non, car MySql dans ce cas là, gère la sérialisation des écritures. Autrement dit, un seul utilisateur est en écriture à un instant donné.

    Citation Envoyé par SergioMaster
    le seul inconvénient d'une SEQUENCE reste dans les Annulations ou Rollbacks , une SEQUENCE ne revient jamais (sauf de façon explicite bien sur) en arrière
    Je suis d'accord. Tout comme l'auto_increment sous MySql car cette variable est stocké en mémoire comme ton generator.

    Citation Envoyé par SergioMaster
    voilà la clé de voute de la "petite polémique"
    Pas du tout. C'est juste un autre argument sur la mauvaise utilisation du Trigger pour résoudre ce problème.

    Citation Envoyé par SergioMaster
    j'ai l'impression que tu n'as pas compris ce qu'est une SEQUENCE pour FIREBIRD et la différence d'avec une variable de contexte. La variable de contexte utilisateur n'existe que le temps de la session contrairement à la SEQUENCE , faisant partie des DDL, et donc de la base de données
    Quand j'ai découvert le "generator", j'ai compris que la variable est stocké dans la base de données. En ce qui concerne la variable de contexte, l'explication est donnée ici :
    Citation Envoyé par RDB$SET_CONTEXT()
    Description: Creates, sets or unsets a variable in one of the user-writable namespaces USER_SESSION and USER_TRANSACTION.
    --> http://www.firebirdsql.org/refdocs/l...t_context.html
    A moins de me tromper, je pense que nous comprenons la même chose.

    Notre divengence d'approche concerne la valeur de NUM_VNT.
    Je pense qu'elle est stockée dans le premier enregistrement du paquet et qu'il ne sait pas comme la reconduire de ligne en ligne dans la table.
    Il propose une solution de contournement, en passant par un generator associé à un trigger.
    Je pense que la bonne façon de faire est de passer par une solution applicative, en gerant une rupture de séquence sur son paquet.

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

  16. #16
    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 381
    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 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut SergioMaster.

    En réponse à ton post #17.

    Je ne suis pas du tout partisan d'utiliser dans une base de données des "auto increment".
    Ce genre de colonne est une solution technique qui vient en remplacement d'un manque de finalisation fonctionnelle sur un MCD.

    Quand j'étais administrateur DB2, je n'ai quasiment jamais rencontré ce genre de solution. Je parle bien de l'auto incrément.
    Inversement, pour distinguer différentes lignes dans une table, une solution parfois utilisée est de mettre un timestamp, dont la valeur descend jusqu'au millionième de seconde.

    J'ai découvert avec effroi que cette pratique est courante dans le monde de la micro-informatique.
    En quoi une colonne technique peut se substituer à un identifiant fonctionnel ?

    Que ce soit une solution applicative ou une solution SGBD, je les rejettes toutes les deux.

    P.S.: par fainéantise dans les solutions que j'apporte, il est vrai que j'utilise cette astuce.
    Mais dans un vrai MCD, je ferais toujours en sorte de trouver un identifiant fonctionnel, porteur d'information !

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

  17. #17
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    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 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour
    Citation Envoyé par Artemus24 Voir le message
    Quand j'étais administrateur DB2, je n'ai quasiment jamais rencontré ce genre de solution. Je parle bien de l'auto incrément.
    moi non plus, du moins pas à ma souvenance, mais ça date plus ou moins de l'époque (80-90) où les bases des SGBDR actuels étaient posées, d'où peut être mon manque de formation à cet égard.

    Citation Envoyé par Artemus24 Voir le message
    Je ne suis pas du tout partisan d'utiliser dans une base de données des "auto increment".
    Ce genre de colonne est une solution technique qui vient en remplacement d'un manque de finalisation fonctionnelle sur un MCD.
    ...
    J'ai découvert avec effroi que cette pratique est courante dans le monde de la micro-informatique.
    En quoi une colonne technique peut se substituer à un identifiant fonctionnel ?
    Que ce soit une solution applicative ou une solution SGBD, je les rejettes toutes les deux.
    ...
    P.S.: par fainéantise dans les solutions que j'apporte, il est vrai que j'utilise cette astuce.
    Mais dans un vrai MCD, je ferais toujours en sorte de trouver un identifiant fonctionnel, porteur d'information !
    C'est là on l'on diverge, quand j'ai des outils disponibles j'essaye de les utiliser au mieux (du moins ceux que je comprends)

    Une colonne technique ne se substitue pas à un identifiant fonctionnel, mais est un complément fort utile et efficace au niveau temps d'accès par exemple, dans mes bases de données l'identifiant fonctionnel est dans un index au lieu d'être une clé primaire c'est la seule entorse d'avec le "old way"
    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

  18. #18
    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 381
    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 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut SergioMaster.

    Citation Envoyé par SergioMaster
    moi non plus, du moins pas à ma souvenance, mais ça date plus ou moins de l'époque (80-90) où les bases des SGBDR actuels étaient posées, d'où peut être mon manque de formation à cet égard.
    Ce sont aussi de vieux souvenir qui date de plus de dix ans maintenant.
    La conception d'une base de données se fait au préalable en passant par une étude fonctionnelle qui débouche sur un MCD.
    A moins de me tromper, je n'ai jamais vu l'usage d'un auto_incrément dans un MCD, sachant qu'il existe déjà des identifiants fonctionnels.
    Le seul usage où je considère qu'il est autorisé d'avoir un auto_incrément est d'avoir une table sans clef primaire.
    Autrement dit, puisque tu n'as pas de clef primaire fonctionnelle, tu crées une clef primaire technique.

    Citation Envoyé par SergioMaster
    C'est là on l'on diverge, quand j'ai des outils disponibles j'essaye de les utiliser au mieux (du moins ceux que je comprends).
    On ne fait pas de la technique sans que celle-ci repose sur une étude fonctionnelle. J'ai beaucoup travaillé dans le domaine bancaire/financier.
    A moins d'avoir plus de liberté d'entreprendre (je sais que c'est le cas en micro-informatique), j'ai toujours eu deux contraintes :
    1) étant un prestataire de service, j'ai toujours été encadré par un supérieur chez le client, même quand j'étais chef de projet.
    2) il y a toujours eu des demandes fonctionnelles qui viennent enrichir la maintenance à effectuer cher le client.
    En résumé, je n'avais aucun liberté dans mes choix. Soit je propose, et elles sont soit acceptés soit refusés, ou alors j'ai un cahier des charges à suivre scrupuleusement.

    Citation Envoyé par SergioMaster
    Une colonne technique ne se substitue pas à un identifiant fonctionnel, mais est un complément fort utile et efficace au niveau temps d'accès par exemple, dans mes bases de données l'identifiant fonctionnel est dans un index au lieu d'être une clé primaire c'est la seule entorse d'avec le "old way"
    L'usage d'un auto_incrément est à l'identique d'un fichier VSAM de type RRDS (Relative Record Data Set) où l'accès ce fait par un numéro relatif d'enregistrement.
    C'est le seul usage, en Cobol sous gros système IBM z/Os où l'on gère un fichier par rapport à un incrément.
    L'organisation LDS (Linear Data Set), qui est utilisé pour le DB2 offre plus de possibilité pour se limiter à un incrément.

    Attention, je parle bien d'un auto_incrément qui sert comme clef primaire à une table.
    Il existe un cas que je tolère, c'est celui d'une clef double où l'on veut éviter les doublons sur la première colonne de cette clef.
    Mais ce cas reste rare car en seconde colonne de la clef, il y a fréquemment une information qui fait la différence :
    --> par exemple la première colonne est le numéro du client.
    puis pour la seconde colonne, tu mets :
    --> date + heure
    --> numéro d'opération servant à identifier l'opération bancaire.

    Ce que je reproche à l'usage de cet auto_incrément repose sur deux points :
    1) le manque d'imagination du concepteur de la base de données pour trouver un véritable identifiant fonctionnel.
    2) insertion des lignes selon l'ordre de stockages. C'est ce qu'il y a de pire comme organisation dans une table. --> Cf. Les clusters.

    Merci pour toutes tes explications SergioMaster. J'ai toujours un grand plaisir à te lire. Tu es ma muse.

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

  19. #19
    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
    Un peu de lecture :

    https://www.coindeweb.net/blogsanssu...-cle-naturelle

    http://sqlpro.developpez.com/cours/clefs/


    Qui tend à préférer les clés de substitution (des clés techniques qui n'ont pas de significations fonctionnelles comme les clés auto-incrémentée ou les GUID ou ROWID).

    Les clés naturelles ont tendances a être composés ce qui devient vitre lourd quand on met en place des contraintes relationnelle. De plus ces clés composés sont souvent moins performante, prennent plus de place et finalement fonctionnellement peuvent devenir vite contraignantes ou difficile à gérer notamment quand on doit changer la valeur de cette clé primaire...


    Exemple :

    Une table Client
    clé primaire : NomClient, PrenomClient

    Premier problème les homonymes...

    Si on veut respecter la méthodologie sans se préoccuper de la technique on prendra d'autres champs fonctionnels :Adresse, Code_postal, Ville
    => clé primaire : NomClient, PrenomClient, AdresseClient, Code_postalClient, VilleClient

    Ajoutons la table INTERVENTIONS
    qui comptabilise les interventions chez les clients.

    INTERVENTIONS
    NOM_CLIENT,
    PRENOM_CLIENT,
    ADRESSECLIENT,
    CODEPOSTALCLIENT
    VILLECLIENT
    NUMERO_INTERVENTION
    DATE_INTERVENTION,
    MOTIF_INTERVENTION
    etc...

    Clé primaire :
    NOM_CLIENT,
    PRENOM_CLIENT,
    ADRESSECLIENT,
    CODEPOSTALCLIENT
    VILLECLIENT
    NUMERO_INTERVENTION

    Clé étrangère :
    NOM_CLIENT,
    PRENOM_CLIENT,
    ADRESSECLIENT,
    CODEPOSTALCLIENT
    VILLECLIENT

    On commence à comprendre que notre table intervention est alourdi par les champs de la table client....

    Imaginons maintenant que mon plus gros client qui a plus de 100 millions d'intervention dans le monde change d'adresse ou de nom....

    Alors oui si on a bien paramétré les clés étrangères, la mise a jour de la table client mettra à jour toutes les ocurences de la table Intervention mais à quelle coût ? 100 millions de mises à jour rien que pour une table intervention. Si cette dernière était lié à d' autres tables comme par exemple facture ou Detail_historique_intervention avec ces mêmes clés composés on peut imaginer arriver facilement au milliards de mise à jour....

    Alors je ne dis pas que la clé auto-incrémenté n'a que des avantages, non, son principal inconvénient est sont manque de signification fonctionnelle pour l'utilisateur final, mais qui se règle par des requêtes avec une jointure supplémentaire pour récupérer des champs fonctionnels à l'utilisateur final.

  20. #20
    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 381
    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 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut Barbibulle.

    Je voie que le sujet t'intéresse.

    Il y a deux notions qui sont mal gérées dans les bases de données, ce sont les clefs et le rangement des lignes dans le support physique (cluster).
    Pourquoi ? Car ce sont des notions physiques alors que les bases relationnelles traitent que de l'aspect logique (théorie des ensembles).

    Hormis les questions relatives à la structure de ces deux types de clefs, SQLPRO résume très bien la finalité de ce que doit être une clef primaire : Concision, Unicité et Stabilité.
    Mais pourquoi remonter les aspects techniques à un niveau fonctionnelle, dont l'utilisateur n'a que faire ? La réponse est : la performance !

    Un mathématicien qui traite de la théorie des ensembles n'a que faire des questions de performances alors que c'est crucial pour une bonne gestion des bases de données.
    A l'origine, les bases dites relationnelles étaient moins performantes que les bases dites réseaux et celle-ci manquaient de souplesses.
    Je me rappelle que l'on présentait une table comme un sac contenant en vrac des lignes sans liens.
    Il a bien fallu trouver une solution physique pour remédier à la performance désastreuse des accès.

    Et la solution a été d'introduire des aspects techniques dans une base de données, juste pour résoudre des questions de performances.
    D'où la divergence d'approche entre les clef dites naturelles (fonctionnelle) et dites de substitutions (technique).
    La question demeure dans la transposition d'un modèle logique en modèle physique.
    On peut se demander si les bases relationnelles sont bien adaptées à ces questions de performances ?

    @+
    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 1 sur 2 12 DernièreDernière

Discussions similaires

  1. communication entre deux executables
    Par semenzato dans le forum MFC
    Réponses: 8
    Dernier message: 13/04/2005, 22h19
  2. Lecture standard et communication entre processus!
    Par Tartar Ukid dans le forum C++Builder
    Réponses: 5
    Dernier message: 05/07/2003, 16h37
  3. Communication entre processus
    Par markopolo dans le forum C++Builder
    Réponses: 2
    Dernier message: 26/06/2003, 16h21
  4. Réponses: 5
    Dernier message: 25/03/2003, 19h43
  5. communication entre programmes
    Par jérôme dans le forum C
    Réponses: 12
    Dernier message: 16/04/2002, 08h05

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