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 :

Trigger pour Mise à jour massive


Sujet :

SQL Firebird

  1. #1
    Membre émérite
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mai 2008
    Messages
    2 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2008
    Messages : 2 401
    Points : 2 304
    Points
    2 304
    Par défaut Trigger pour Mise à jour massive
    Salut !
    comme à chaque fois, on revient vers vous quand on bloque
    commençons par le code
    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
    AS
    declare variable n_org integer;
    declare variable n_ordre smallint;
    declare variable i smallint;
    begin
      for
      select lo.num_organe, eo.num_ordre from tb_eq_org_type eo
      inner join tb_liste_equipement le on (le.numero_equpement = eo.num_eq)
      inner join tb_liste_organe lo on (lo.num_organe = eo.num_org)
      where (le.numero_equpement =(select e.numero_equipement from tb_equipement e
                where (e.code_equipement = new.code_equipement)))
     
      into :n_org,
           :n_ordre
      do
      begin
        if (row_count > 0) then
        begin
          new.num_ordre = n_ordre;
          new.num_organe = n_org;
          if (char_length(new.num_ordre) < 2) then
          new.CODE_ORGANE = new.code_equipement || '-0' || new.num_ordre;
          else new.CODE_ORGANE = new.code_equipement || '-' || new.num_ordre;
          suspend;
        end
        else exception Liste_Vide;
      end
    end
    et maintenant l'explication....
    J'ai une table organe et une autre table équipement. Un équipement peut avoir un ou plusieurs organes, je voulais automatiser la MAJ de la table Organe par la mise en place d'autre tables listes; liste_équipement et liste_orage, ces deux tables vont construite une troisième table equipement_organe_type. Je donne un exemple, une vanne est constituée de plusieurs organes; volant, tige et paroi. Cet équipement figure dans plusieurs endroits de ma station de traitement. Ce que je veux c'est quand j'associe la vanne à un ouvrage, mon SGBDR soit capable d'ajouter autant de lignes à la table organe. Donc il commence par faire une petite recherche dans la table equipement_organe_type et insère les lignes trouvées en conséquence.

    Là je suis à mi-chemin car, même avec une boucle FOR, je n'ai que la dernière lignes insérée dans ma table Organe ! où sont passées les autres lignes ?

    Une aide, une piste .... et un grand merci
    Bon courage ou Bonne Chance (selon le contexte)
    Mon blog sur WordPress

  2. #2
    Rédacteur/Modérateur

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

    le trigger est déclenché quand , sur quelle table ?
    et , si j'ai bien compris il doit manquer une instruction INSERT INTO equipement_organe_type () VALUES .... dans la boucle FOR
    je ne suis pas sur non plus que le IF (row_count > 0) then soit nécessaire mais je n'ai fait que survoler la question
    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
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Haute Garonne (Midi Pyrénées)

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

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 784
    Points : 5 915
    Points
    5 915
    Par défaut
    Bonjour,
    Citation Envoyé par Just-Soft Voir le message
    et maintenant l'explication....
    Je l'ai déjà dit en d'autres occasions, mais un jeu d'essai avec le résultat attendu permet de mieux comprendre votre problématique et léver des ambiguités et sous-entendus...

    Citation Envoyé par Just-Soft Voir le message
    Là je suis à mi-chemin car, même avec une boucle FOR, je n'ai que la dernière lignes insérée dans ma table Organe ! où sont passées les autres lignes ?
    La boucle FOR parcourt une à une les lignes de l'ensemble de données résultant de votre requête et affecte le résultat à des variables (new.*). En sortie de boucle, ce sont donc les valeurs de la dernière itération qui seront prises en compte.
    Comme l'a dit SergioMaster, il faudrait une instruction INSERT INTO... dans la boucle. A vérifier cependant car on est dans le code d'un déclencheur et on risque d'insérer plus de lignes que voulues (d'où ma demande sur le jeu d'essai).

    C'est un déclencheur sur insertion, mise à jour, les deux ?
    Philippe.

  4. #4
    Membre émérite
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mai 2008
    Messages
    2 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2008
    Messages : 2 401
    Points : 2 304
    Points
    2 304
    Par défaut oh oh
    Merci à vous deux ...
    le trigger est sur la table Organe. C'est un trigger before insert, mais je me suis aperçu qu'il est impossible de le faire du moment que l'insertion doit se faire dans la table Organe. Donc, à l'insertion de la ligne le trigger est appelé et va en même temps insérer des lignes ce qui enclenchera un nouvel appel du trigger est ainsi de suite.

    Alors, en toute sagesse j'ai résolu une 1ère partie en codant tout ça dans une PS. Pour toute fin utile voici le code :

    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
    CREATE PROCEDURE PS_MAJ_ORGANE (
        code_equipement varchar(13))
    as
    declare variable n_org integer;
    declare variable n_ordre smallint;
    declare variable code_org varchar(18);
    begin
      for
      select lo.num_organe, eo.num_ordre from tb_eq_org_type eo
      inner join tb_liste_equipement le on (le.numero_equpement = eo.num_eq)
      inner join tb_liste_organe lo on (lo.num_organe = eo.num_org)
      where (le.numero_equpement =(select e.numero_equipement from tb_equipement e
             where (e.code_equipement =:code_equipement)))
     
      into :n_org,
           :n_ordre
      do
      begin
        if (row_count > 0) then
        begin
          select o.code_organe from tb_organe o
          where (o.code_equipement=:code_equipement and o.num_organe=:n_org)
          into :code_org;
     
          if (row_count > 0) then exception Organe_deja_saisie;
          else begin
            insert into tb_organe (code_equipement, num_organe, num_ordre)
            values (:code_equipement, :n_org, :n_ordre);
          end
        end
        else exception Liste_Vide;
      end
    end
    Bon courage ou Bonne Chance (selon le contexte)
    Mon blog sur WordPress

  5. #5
    Rédacteur/Modérateur

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

    Je pense que cela doit pouvoir se simplifier , mais comme le dit Philippe avec la description des tables, leur relation et un jeu d'essai cela serait plus facile .

    en fait je pense que les termes que tu emplois pour le nom de tes tables augmente ma confusion

    en gestion de production , j'ai des produits qui ont <une nomenclature qui est composée <de matières
    je présume que dans le description d'une station ? <tu as des équipements ? <composés d'élements ?

    ce qui me perturbe c'est le besoin d'avoir la table détaillée equipements_station ( quoique , en gestion de production je garde une trace de la nomenclature utilisée pour un ordre de fabrication)


    si j'ai compris et en utilisant ton exemple , on a dans la base 2 tables de départ liste_equipement et liste_Organe
    une vanne est constituée de plusieurs organes; volant, tige et paroi.
    la table liste equipement contient
    VANNE VOLANT
    VANNE TIGE
    VANNE PAROI
    pour une table liste_ORGANE
    VOLANT
    TIGE
    PAROI
    et donc lorsque tu ajoute un nouvel équipement dans une autre table Equipement_Station par exemple tu veux obtenir un ensemble d'enregistrement
    par exemple pour l'ajout d'une vanne avec l''identification 10 tu veux obtenir 'automatiquement'
    10 VANNE VOLANT
    10 VANNE TIGE
    10 VANNE PAROI
    si c'est le cas il faut utiliser une PS et non un déclencheur . en fait un SQL
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    INSERT INTO EQUIPEMENT_STATION(ID,EQUIPEMENT,ORGANE) SELECT '10',code_equipement,code_organe FROM liste_equipement WHERE code_equipement='VANNE'
    ferait l'affaire

    un (des) trigger(s) sur le table liste_equipement (je n'aime pas trop le nom) pourrait par contre être utile si la composition change , par exemple ajout d'un ECROU

    Ajout de VANNE ECROU à la table liste_equipement
    le trigger after insert ressemblerai en gros à ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    FOR SELECT ID FROM EQUIPEMENT_STATION WHERE EQUIPEMENT='VANNE' INTO :ID 
      DO
      INSERT INTO EQUIPEMENT_STATION(ID,EQUIPEMENT,ORGANE) VALUES :ID,:new.code_equipement,:new.code_organe
    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

  6. #6
    Membre émérite
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mai 2008
    Messages
    2 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2008
    Messages : 2 401
    Points : 2 304
    Points
    2 304
    Par défaut Le jeu de données et une explication
    Tout d'abord je tiens à vous remercier et à m'excuser pour ne pas avoir donner les détails nécessaire.
    Le jeu de données :
    Equipement {num_equip}
    Organe {num_organe, num_equip}
    Organe_Entretien {code_organe, code_entretien}
    Liste_Equipement {num_organe, designation}
    Liste_Organe {num_organe, designation}
    Liste_Equipement_Organe_Type {num_equip, num_organe}
    Liste_Organe_Entretien_Type {num_organe, code_entretien}

    Les relations:
    un équipement est constitué de un ou plusieurs organes
    un organe subit au moins un entretien

    Méthodologie de MAJ:
    Afin de simplifier la MAJ, j'ai créé des listes types et ceci dans le but d'automatiser la chose. Donc, ce que j'ai à faire c'est de renseigner le numéro d'un équipement et la PS se charge de chercher les organes de cet équipement depuis la liste type (Liste_Equipement_Organe_Type) de même pour les entretien et ceci afin d'insérer l'organe en question dans la table organe et les entretiens dans la table Organe_Entretien.

    Le code de la PS:
    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
    CREATE PROCEDURE PS_MAJ_ORGANE (
        code_equipement varchar(13))
    as
    declare variable n_org integer;
    declare variable n_ordre smallint;
    declare variable code_org varchar(18);
    declare variable code_entretien varchar(2);
    begin
      for
      select lo.num_organe, eo.num_ordre from tb_eq_org_type eo
      inner join tb_liste_equipement le on (le.numero_equpement = eo.num_eq)
      inner join tb_liste_organe lo on (lo.num_organe = eo.num_org)
      where (le.numero_equpement =(select e.numero_equipement from tb_equipement e
             where (e.code_equipement =:code_equipement)))
     
      into :n_org,
           :n_ordre
      do
      begin
        if (row_count > 0) then
        begin
          select o.code_organe from tb_organe o
          where (o.code_equipement=:code_equipement and o.num_organe=:n_org)
          into :code_org;
     
          if (row_count > 0) then exception Organe_deja_saisie;
          else begin
            insert into tb_organe (code_equipement, num_organe, num_ordre)
            values (:code_equipement, :n_org, :n_ordre);
     
            /* erreur : plusieurs lignes dans une requête qui devrait rendre une seule ligne */
            select o.code_organe from tb_organe o
            inner join tb_equipement e on (e.code_equipement = o.code_equipement)
            where (o.num_organe=:n_org and o.num_ordre=:n_ordre)
            into :code_org;
     
              for
                select oe.num_organe, le.code_entretien from tb_org_entretien_type oe
                inner join tb_liste_entretien le on (le.code_entretien = oe.code_entretien)
                inner join tb_organe o on (oe.num_organe = o.num_organe)
                where (o.code_organe =:code_org)
     
                into :n_org,
                     :code_entretien
              do
              begin
                if (row_count > 0) then
                begin
                  insert into tb_organe_entretien (code_organe, code_etretien)
                  values (:code_org, :code_entretien);
                end
                else exception Liste_Vide;
              end
          end
        end
        else exception Liste_Vide;
      end
    end
    Pour la MAJ Equipement --> Organe tout marche bien
    Mais l'erreur est dans la partie Organe-->Entretien, probablement il manque un critère dans le where .... je travaille dessus

    Voilà, je crois que c'est plus clair là .....
    Bon courage ou Bonne Chance (selon le contexte)
    Mon blog sur WordPress

  7. #7
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 038
    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 038
    Points : 40 943
    Points
    40 943
    Billets dans le blog
    62
    Par défaut
    Bonjour,
    Citation Envoyé par Just-Soft Voir le message
    Voilà, je crois que c'est plus clair là .....
    Moins , car tu ajoutes une table qui jusque là n'avais pas été évoqué (entretien) .

    Ensuite , je pense réellement que tes querys sont simplifiables , la gestion des exceptions est-elle obligatoire ?
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  8. #8
    Membre émérite
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mai 2008
    Messages
    2 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2008
    Messages : 2 401
    Points : 2 304
    Points
    2 304
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Moins , car tu ajoutes une table qui jusque là n'avais pas été évoqué (entretien) .
    OK mais c'est compréhensible je pense .... non !

    Citation Envoyé par SergioMaster Voir le message
    Ensuite , je pense réellement que tes querys sont simplifiables ?
    Je suis preneur

    Citation Envoyé par SergioMaster Voir le message
    Ela gestion des exceptions est-elle obligatoire ?
    Je crois que oui, le teste se fait sous IBExpert par d'autres personnes, c'est plus clair avec les messages personnalisés
    Bon courage ou Bonne Chance (selon le contexte)
    Mon blog sur WordPress

  9. #9
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 038
    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 038
    Points : 40 943
    Points
    40 943
    Billets dans le blog
    62
    Par défaut
    Bonjour,
    Citation Envoyé par Just-Soft Voir le message
    OK mais c'est compréhensible je pense .... non !
    oui , c'était juste une boutade
    Je crois que oui, le test se fait sous IBExpert par d'autres personnes, c'est plus clair avec les messages personnalisés

    Donc, ce que j'ai à faire c'est de renseigner le numéro d'un équipement et la PS se charge de chercher les organes de cet équipement depuis la liste type (Liste_Equipement_Organe_Type) de même pour les entretien et ceci afin d'insérer l'organe en question dans la table organe et les entretiens dans la table Organe_Entretien.
    reste que ces deux dernières tables me semblent inutile , bon enfin ce n'est pas moi le DBA

    je suis preneur
    j'allais proposer une correction mais décidément , les informations de structure des tables me paraissent insuffisantes par exemple : où est le num_ordre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT lo.num_organe, eo.num_ordre FROM tb_eq_org_type eo
    ?

    Puisque tu utilises IBExpert pourquoi ne pas me/nous sortir les scripts de création des tables , c'est quand même pas SECRET DEFENSE , je présume que les champs entre {} sont uniquement les clés mais

    je propose ceci : les champs en {} sont les Clés primaires en [les clés étrangères] (relations)
    Equipement {num_equip}[type_equipement] << ici j'ai rajouté type_equipement, en FK
    Organes_Equipement {num_equip+num_organe} num_ordre
    Entretien_Equipement {num_equip+code_entretien}

    Liste_Equipement_Organe_Type {type_equipement} [num_organe] num_ordre << ici j'ai changé le num_equip par type_equipement
    Entretien_Equipement_Type {num_organe] [code_entretien]
    (ces deux dernières tables , en gestion de production seraient respectivement les nomenclatures et gammes opératoires)

    si les tables Liste_Equipement,Liste_Organe ne contiennent que la désignation pas la peine de les fournir et elles ne servent pas dans la PS

    sans gestion des exceptions (rapidement transformable en trigger) cela donnerait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CREATE PROCEDURE PS_NOUVEL_EQUIPEMENT (
        code_equipement varchar(13),
        TYPE_EQUIPEMENT ...)
    AS
    INSERT INTO ORGANES_EQUIPEMENT(num_equip,num_organe,num_ordre) SELECT :code_equipement,num_organe,num_ordre FROM LISTE_EQUIPEMENT_ORGANE_TYPE
    WHERE TYPE_EQUIPEMENT=:TYPE_EQUIPEMENT;
    INSERT INTO Entretien_Equipement (num_equip,CODE_ENTRETIEN) SELECT :Code_equipement,ee.CODE_ENTRETIEN FROM 
    FROM LISTE_EQUIPEMENT_ORGANE_TYPE LEO INNER JOIN Entretien_Equipement_Type EE ON LEO.NUM_ORGANE=EE.NUM_ORGANE 
    WHERE TYPE_EQUIPEMENT=:TYPE_EQUIPEMENT;
    END;
    P.S. S.T.P. si une table de ta description se nomme Liste_Equipement_Organe_Type pourquoi la retrouver dans la PS nommée tb_eq_org_type !
    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
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 038
    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 038
    Points : 40 943
    Points
    40 943
    Billets dans le blog
    62
    Par défaut
    re,
    voilà une création rapide , c'est un peu ceci (en mieux) que je/on aurait voulu avoir
    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
     
    /******************* PROCEDURES ******************/
     
    SET TERM ^ ;
    CREATE PROCEDURE SIMUL_NEW_EQUIPEMENT (
        NUM_EQUIPEMENT Integer,
        TYPE_EQUIPEMENT Integer )
    RETURNS (
        NUMERO Integer,
        ORDRE Integer,
        ORGANE Integer,
        DESIGNATION Varchar(13) )
    AS
    BEGIN SUSPEND; END^
    SET TERM ; ^
     
    SET TERM ^ ;
    CREATE PROCEDURE SIMUL_NEW_EQUIPEMENT_ENTRETIEN (
        NUM_EQUIPEMENT Integer,
        TYPE_EQUIPEMENT Integer )
    RETURNS (
        NUMERO Integer,
        ENTRETIEN Integer,
        ORGANE Integer,
        DESIGNATION_ORGANE Varchar(13),
        DESIGNATION_ENTRETIEN Varchar(13) )
    AS
    BEGIN SUSPEND; END^
    SET TERM ; ^
     
    /******************** TABLES **********************/
     
    CREATE TABLE ENTRETIEN_TYPE
    (
      CODE_TYPE_ENTRETIEN Integer NOT NULL,
      CODE_ORGANE Integer NOT NULL,
      DESIGNATION Varchar(13),
      CONSTRAINT PK_ENTRETIEN_TYPE PRIMARY KEY (CODE_TYPE_ENTRETIEN,CODE_ORGANE)
    );
    CREATE TABLE EQUIPEMENTS
    (
      NUM_EQUIPEMENT Integer NOT NULL,
      NOM_EQUIPEMENT Varchar(13),
      CODE_TYPE_EQUIPEMENT Integer,
      CONSTRAINT PK_EQUIPEMENT PRIMARY KEY (NUM_EQUIPEMENT)
    );
    CREATE TABLE EQUIPEMENT_TYPE
    (
      CODE_TYPE_EQUIPEMENT Integer NOT NULL,
      CODE_ORGANE Integer NOT NULL,
      NUM_ORDRE Integer,
      DESIGNATION Varchar(13),
      CONSTRAINT PK_EQUIPEMENT_TYPE PRIMARY KEY (CODE_TYPE_EQUIPEMENT,CODE_ORGANE)
    );
     
    SET TERM ^ ;
    ALTER PROCEDURE SIMUL_NEW_EQUIPEMENT (
        NUM_EQUIPEMENT Integer,
        TYPE_EQUIPEMENT Integer )
    RETURNS (
        NUMERO Integer,
        ORDRE Integer,
        ORGANE Integer,
        DESIGNATION Varchar(13) )
    AS
    BEGIN
     FOR
      SELECT :NUM_EQUIPEMENT,NUM_ORDRE,CODE_ORGANE,DESIGNATION FROM EQUIPEMENT_TYPE
      WHERE CODE_TYPE_EQUIPEMENT=:TYPE_EQUIPEMENT
      INTO :NUMERO,:ORDRE,:ORGANE,:DESIGNATION 
     DO SUSPEND; 
    END^
    SET TERM ; ^
     
     
    SET TERM ^ ;
    ALTER PROCEDURE SIMUL_NEW_EQUIPEMENT_ENTRETIEN (
        NUM_EQUIPEMENT Integer,
        TYPE_EQUIPEMENT Integer )
    RETURNS (
        NUMERO Integer,
        ENTRETIEN Integer,
        ORGANE Integer,
        DESIGNATION_ORGANE Varchar(13),
        DESIGNATION_ENTRETIEN Varchar(13) )
    AS
    BEGIN
     FOR
      SELECT :NUM_EQUIPEMENT,ET.CODE_TYPE_ENTRETIEN,OT.CODE_ORGANE,OT.DESIGNATION,ET.DESIGNATION FROM EQUIPEMENT_TYPE OT 
      INNER JOIN ENTRETIEN_TYPE ET ON OT.CODE_ORGANE=ET.CODE_ORGANE
      WHERE CODE_TYPE_EQUIPEMENT=:TYPE_EQUIPEMENT
      INTO :NUMERO,:ENTRETIEN,:ORGANE,:DESIGNATION_ORGANE,:DESIGNATION_ENTRETIEN
     DO SUSPEND; 
    END^
    SET TERM ; ^
    Ainsi qu'un jeu d'essai (encore + rapide)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    INSERT INTO EQUIPEMENT_TYPE (CODE_TYPE_EQUIPEMENT, CODE_ORGANE, NUM_ORDRE, DESIGNATION) VALUES ('1', '1', '1', 'ECROU');
    INSERT INTO EQUIPEMENT_TYPE (CODE_TYPE_EQUIPEMENT, CODE_ORGANE, NUM_ORDRE, DESIGNATION) VALUES ('1', '2', '2', 'VOLANT');
    INSERT INTO EQUIPEMENT_TYPE (CODE_TYPE_EQUIPEMENT, CODE_ORGANE, NUM_ORDRE, DESIGNATION) VALUES ('1', '3', '3', 'MANETTE');
    INSERT INTO ENTRETIEN_TYPE (CODE_TYPE_ENTRETIEN, CODE_ORGANE, DESIGNATION) VALUES ('1', '2', 'REMPLACEMENT');
    et pour obtenir les résultats
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT p.NUMERO, p.ORDRE, p.ORGANE, p.DESIGNATION FROM SIMUL_NEW_EQUIPEMENT (130, 1) p
    SELECT p.NUMERO, p.ENTRETIEN, p.ORGANE, p.DESIGNATION_ORGANE, p.DESIGNATION_ENTRETIEN FROM SIMUL_NEW_EQUIPEMENT_ENTRETIEN (103, 1) p
    [Edit] avec des triggers (sujet de départ) cela donnerait
    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
    CREATE TABLE LISTE_ORGANES
    (NUM_EQUIPEMENT INTEGER,
     CODE_ORGANE INTEGER,
     CONSTRAINT PK_LISTEORGANES PRIMARY KEY (NUM_EQUIPEMENT,CODE_ORGANE)
     );
     
    CREATE TABLE LISTE_ENTRETIEN
    (NUM_EQUIPEMENT INTEGER,
     CODE_ENTRETIEN INTEGER,
     CONSTRAINT PK_LISTEENTRETIEN PRIMARY KEY (NUM_EQUIPEMENT,CODE_ENTRETIEN)
     );
     
    SET TERM ^ ;
     
    CREATE TRIGGER CREER_EQUIPEMENT FOR EQUIPEMENTS
    ACTIVE AFTER INSERT POSITION 0
    AS 
    BEGIN 
       INSERT INTO LISTE_ORGANES (NUM_EQUIPEMENT,CODE_ORGANE)
         SELECT NEW.NUM_EQUIPEMENT,CODE_ORGANE FROM EQUIPEMENT_TYPE
         WHERE CODE_TYPE_EQUIPEMENT=NEW.CODE_TYPE_EQUIPEMENT;
     
       INSERT INTO LISTE_ENTRETIEN (NUM_EQUIPEMENT,CODE_ENTRETIEN)
        SELECT NEW.NUM_EQUIPEMENT,ET.CODE_ENTRETIEN FROM EQUIPEMENT_TYPE OT 
        INNER JOIN ENTRETIEN_TYPE ET ON OT.CODE_ORGANE=ET.CODE_ORGANE
        WHERE CODE_TYPE_EQUIPEMENT=:NEW.CODE_TYPE_EQUIPEMENT 
     
    END^
     
    SET TERM ; ^
    Sur ce , je me met au boulot , c'est l'heure
    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. #11
    Membre émérite
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mai 2008
    Messages
    2 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2008
    Messages : 2 401
    Points : 2 304
    Points
    2 304
    Par défaut
    Merci encore Serge ...
    mais je peux vous assurer qu'il n'y a aucun secret défense (rire). Oui, j'ai omis de donner plus de détails mais pour le choix des tables je peux aussi vous assurer qu'elles sont toutes utiles.
    Je vais donner le dernier code qui marche assez bien pour le moment et pour la compréhension j'ajoute la définition des différentes tables avec quelques données.

    Le code
    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
    CREATE PROCEDURE PS_MAJ_ORGANE (
        code_equipement varchar(13))
    as
    declare variable n_org integer;
    declare variable n_ordre smallint;
    declare variable code_org varchar(18);
    declare variable code_entretien varchar(2);
    declare variable freq_entretien varchar(20);
    declare variable type_entretien varchar(2);
    declare variable nature_entretin varchar(10);
    begin
      for
      select lo.num_organe, eo.num_ordre from tb_eq_org_type eo
      inner join tb_liste_equipement le on (le.numero_equpement = eo.num_eq)
      inner join tb_liste_organe lo on (lo.num_organe = eo.num_org)
      where (le.numero_equpement =(select e.numero_equipement from tb_equipement e
             where (e.code_equipement =:code_equipement)))
     
      into :n_org,
           :n_ordre
      do
      begin
        if (row_count > 0) then
        begin
     
          /* recherche du code */
          select o.code_organe from tb_organe o
          where (o.num_organe=:n_org and o.code_equipement=:code_equipement)
          into :code_org;
     
          /* si trouver alors message */
          if (row_count > 0) then exception Organe_deja_saisie;
     
          /* sinon insetion */
          else begin
            insert into tb_organe (code_equipement, num_organe, num_ordre)
            values (:code_equipement, :n_org, :n_ordre);
          end
     
          /* renseigner la clef (code organe) */
          select o.code_organe, o.num_organe from tb_organe o
          where (o.num_organe=:n_org and o.code_equipement=:code_equipement)
          into :code_org, :n_org;
     
          /* une recherche sur les entretiens d'un organe X */
          for
            select oe.code_entretien, oe.freq_entretien || ' ' ||oe.unite_freq ,
            oe.code_type_entretien, oe.nature_organe from tb_org_entretien_type oe
            inner join tb_organe o on (oe.num_organe = o.num_organe)
            where (o.code_organe=:code_org and o.num_organe=:n_org)
            into :code_entretien, :freq_entretien, :type_entretien, :nature_entretin
     
         /* insertion dans la tables des entretins des organes */
          do
          begin
            insert into tb_organe_entretien (code_organe, code_etretien, frequence, type_entretien, nature_entretien)
            values (:code_org, :code_entretien, :freq_entretien, :type_entretien, :nature_entretin);
          end
        end
        else exception Liste_Vide;
      end
    end
    La définition des tables et quelques données

    CREATE TABLE TB_LISTE_ORGANE (
    NUM_ORGANE INTEGER NOT NULL,
    DESIGNATION VARCHAR(80)
    );

    NUM_ORGANE DESIGNATION
    1 Tige filetée
    2 Joint d'étanchéité de la paroi
    3 Palier de guidage
    4 Roulement du volant
    5 Grille statique
    6 Roue

    CREATE TABLE TB_LISTE_ORGANE (
    NUM_ORGANE INTEGER NOT NULL,
    DESIGNATION VARCHAR(80)
    );
    CODE_TYPE DESIGNATION
    01 Systematique
    02 Periodique
    03 Conditionnel
    04 Reparation
    05 Depanage
    06 Amelioration

    CREATE TABLE TB_LISTE_ENTRETIEN (
    CODE_ENTRETIEN VARCHAR(20) NOT NULL,
    DESIGNATION VARCHAR(100)
    );
    CODE_ENTRETIEN DESIGNATION
    01 Graissage
    02 Degrippage
    03 Vérification
    04 Nettoyage
    05 Contrôle des aubes
    06 Contrôle du jeu et réglage
    07 Vérification ou changement de la garniture si c'est necessaire
    08 Vidange et lubrification

    CREATE TABLE TB_ORGANE_ENTRETIEN (
    CODE_ORGANE VARCHAR(20) NOT NULL,
    CODE_ETRETIEN VARCHAR(20) NOT NULL,
    TYPE_ENTRETIEN VARCHAR(20),
    FREQUENCE VARCHAR(20),
    TEMPS_INTERVENTION DOUBLE PRECISION,
    TRACABILITE VARCHAR(5),
    OUTILLAGE VARCHAR(50),
    NATURE_ENTRETIEN VARCHAR(10)
    );
    CODE_ORGANE CODE_ETRETIEN TYPE_ENTRETIEN FREQUENCE TEMPS_INTERVENTION
    44STEP01E0303-01 01 02 6 mois MECANIQUE
    44STEP01E0303-01 03 02 3 mois ELECTRIQUE
    44STEP01E0303-01 10 02 6 mois MECANIQUE
    44STEP01E0303-01 11 01 7000 heures MECANIQUE
    44STEP01E0303-01 12 01 7000 heures ELECTRIQUE
    44STEP01E0303-01 13 02 6 mois ELECTRIQUE
    44STEP01E0303-01 14 02 6 mois ELECTRIQUE
    44STEP01E0303-01 19 02 6 mois ELECTRIQUE
    44STEP01E0303-02 08 01 8000 heures MECANIQUE
    44STEP01E0303-02 20 02 1 mois MECANIQUE
    44STEP01E0303-02 21 02 8000 heures MECANIQUE
    44STEP01E0303-04 01 02 6 mois MECANIQUE
    44STEP01E0303-04 03 02 6 mois MECANIQUE

    CREATE TABLE TB_ORGANE (
    CODE_EQUIPEMENT VARCHAR(20) NOT NULL,
    NUM_ORDRE VARCHAR(2) NOT NULL,
    CODE_ORGANE VARCHAR(20) NOT NULL,
    NUM_ORGANE SMALLINT NOT NULL
    );
    CODE_EQUIPEMENT NUM_ORDRE CODE_ORGANE NUM_ORGANE
    44STEP01A0101 1 44STEP01A0101-01 9
    44STEP01A0101 2 44STEP01A0101-02 48
    44STEP01A0101 3 44STEP01A0101-03 49
    44STEP01A0201 1 44STEP01A0201-01 50
    44STEP01A0201 2 44STEP01A0201-02 51
    44STEP01A0201 3 44STEP01A0201-03 52
    44STEP01A0201 4 44STEP01A0201-04 53
    44STEP01A0201 5 44STEP01A0201-05 54
    44STEP01A0201 6 44STEP01A0201-06 55
    44STEP01A0201 7 44STEP01A0201-07 56
    44STEP01A0201 8 44STEP01A0201-08 57
    44STEP01A0201 9 44STEP01A0201-09 58
    44STEP01A0201 10 44STEP01A0201-10 59
    44STEP01A0201 11 44STEP01A0201-11 60
    44STEP01A0201 12 44STEP01A0201-12 61
    44STEP01A0201 13 44STEP01A0201-13 62
    44STEP01A0202 1 44STEP01A0202-01 63

    J'espère qu'avec ça la vue est plus lisible
    Bon courage ou Bonne Chance (selon le contexte)
    Mon blog sur WordPress

  12. #12
    Rédacteur/Modérateur

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

    J'espère qu'avec ça la vue est plus lisible
    oui , cependant j'eusse préféré le jeu d'essai comme le mien , c.a.d avec des SQL INSERT

    ensuite , je persiste a penser que 2 boucles for c'est une de trop
    et que le select du FOR est améliorable :
    - j'aime pas vraiment le WHERE (le.numero_equpement =(SELECT ... WHERE ...))
    - j'aime pas trop tout ces appels à row_count

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     /* recherche du code */
          SELECT o.code_organe FROM tb_organe o
          WHERE (o.num_organe=:n_org AND o.code_equipement=:code_equipement)
          INTO :code_org;
     
          /* si trouver alors message */
          IF (row_count > 0) then exception Organe_deja_saisie;
    pourrait se remplacer par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    IF (EXISTS (SELECT 1 FROM tb_organe WHERE num_organe=:n_org AND code_equipement=:code_equipement)) 
        THEN exception Organe_deja_saisi;
    etc...enfin si la procédure fonctionne , je vais pas me casser la tête
    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

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

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

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 784
    Points : 5 915
    Points
    5 915
    Par défaut
    Bonjour,
    Citation Envoyé par SergioMaster Voir le message
    oui , cependant j'eusse préféré le jeu d'essai comme le mien , c.a.d avec des SQL INSERT
    Moi aussi, mais je crains qu'on ne soit pas assez convaincant...

    Citation Envoyé par SergioMaster Voir le message
    ensuite , je persiste a penser que 2 boucles for c'est une de trop
    Je pense aussi, mais je ne me suis pas autant penché sur le problème que vous.

    Citation Envoyé par SergioMaster Voir le message
    et que le select du FOR est améliorable :
    - j'aime pas vraiment le WHERE (le.numero_equpement =(SELECT ... WHERE ...))
    Moi non plus, les sous-requêtes sont préjudiciables aux performances, d'autant plus que celle-ci peut AMHA être remplacée par une jointure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      for
      select lo.num_organe, eo.num_ordre
      from tb_eq_org_type eo
      inner join tb_liste_equipement le on le.numero_equpement = eo.num_eq
      inner join tb_liste_organe lo on lo.num_organe = eo.num_org
      inner join tb_equipement e on e.numero_equipement = le.numero_equpement  --where (le.numero_equpement =(select e.numero_equipement from tb_equipement e
      where e.code_equipement = :code_equipement                               --       where (e.code_equipement =:code_equipement)))
     
      into :n_org,
           :n_ordre
    Citation Envoyé par SergioMaster Voir le message
    - j'aime pas trop tout ces appels à row_count
    Surtout qu'imbriqués, cela peut amener à des résultats... innattendus...
    Philippe.

  14. #14
    Membre émérite
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mai 2008
    Messages
    2 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2008
    Messages : 2 401
    Points : 2 304
    Points
    2 304
    Par défaut
    Merci Merci ...
    Je commence par le mot de fin ..... oui la procédure marche très bien et les résultats sont là ... mais, je crois qu'avec vos suggestions je pourrais avoir quelque chose de plus performant.

    Juste un petit commentaire sur deux points :
    1. Les deux boucles imbriquées : je crois que la logique Equipement -- Organe puis Organe -- Entretien sont à l'origine de cette logique que j'ai suivi. Un équipement à un organe au moins et celui-ci subit au moins un entretien, donc le fait d'insérer un équipement celui-là doit être capable de reconnaître ses organes, qui eux à leur tour, doivent savoir quel entretien ils doivent subir.
    2. Pour ce qui est du row_count, je n'ai pas trouvé dans la documentation firebird qu'il est déconseillé et je ne l'utilise que pour tester l'existence de lignes satisfaisant à un ou à des critères.



    si vous avez d'autres conseils je suis preneur.
    Bon courage ou Bonne Chance (selon le contexte)
    Mon blog sur WordPress

  15. #15
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 038
    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 038
    Points : 40 943
    Points
    40 943
    Billets dans le blog
    62
    Par défaut
    BONJOUR
    Citation Envoyé par Just-Soft Voir le message
    Les deux boucles imbriquées : je crois que la logique Equipement -- Organe puis Organe -- Entretien sont à l'origine de cette logique que j'ai suivi. Un équipement à un organe au moins et celui-ci subit au moins un entretien, donc le fait d'insérer un équipement celui-là doit être capable de reconnaître ses organes, qui eux à leur tour, doivent savoir quel entretien ils doivent subir.
    Si tu regardes le trigger que j'ai proposé , en utilisant les INSERT INTO SELECT tu remarqueras que je n'ai même pas besoin de boucles FOR
    Si tu veux gérer le nombre d'enregistrements retourné par le INSERT , c'est possible avec RETURNING VALUE
    Pour ce qui est du row_count, je n'ai pas trouvé dans la documentation firebird qu'il est déconseillé et je ne l'utilise que pour tester l'existence de lignes satisfaisant à un ou à des critères.
    Testes par EXISTS comme je l'ai indiqué , où , si tu utilises RETURNING VALUES tu testes la valeur , après et non avant
    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

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 10/06/2014, 21h26
  2. Réponses: 2
    Dernier message: 13/05/2014, 12h46
  3. Trigger pour mise à jour
    Par dellys2 dans le forum PL/SQL
    Réponses: 4
    Dernier message: 21/11/2011, 21h14
  4. [VB6] Code pour Mise à jour automatique
    Par marsup54 dans le forum VB 6 et antérieur
    Réponses: 45
    Dernier message: 10/02/2006, 18h05
  5. Utilisation de CASCADE pour mise à jour
    Par fuelcontact dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 16/08/2004, 08h49

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