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 :

Mise à jour d'une relation Père - fils


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 Mise à jour d'une relation Père - fils
    Bonjour !

    Je me trouve coincé dans une mise à jour qui me paraissait jusqu'ici simple. En effet, je voulais reproduire la mise à jour manuelle par un automate. J'ai deux tables :
    tb_Hist_Entretien
    CREATE TABLE TB_HIS_ENTRETIEN (
    NUMERO_ENTRETIEN BIGINT NOT NULL,
    DATE_INTER DATE NOT NULL,
    DATE_PANNE DATE,
    CODE_ORGANE VARCHAR(20),
    CODE_ENTRETIEN SMALLINT,
    CAUSE VARCHAR(20),
    DATE_PREV DATE,
    APPRECIATION_ENTRETIEN VARCHAR(20),
    HEURE_MARCHE_CUMUL SMALLINT,
    INTERVENANT VARCHAR(50) DEFAULT 'STAFF ONA STEP',
    N_ODS VARCHAR(9),
    TEMPS_ARRET_MACHINE_H SMALLINT,
    TEMPS_INTERVENTION_H SMALLINT,
    PIECE_RECHANGE_DA SMALLINT,
    MAIN_DOEUVRE_DA SMALLINT,
    TOTAL_DA BIGINT,
    CUMMUL_DA SMALLINT
    );

    ALTER TABLE TB_HIS_ENTRETIEN ADD CONSTRAINT PK_TB_HIS_ENTRETIEN PRIMARY KEY (NUMERO_ENTRETIEN);
    et une autre table tb_Calendrier
    CREATE TABLE TB_CALENDRIER (
    CODE_ORGANE VARCHAR(20) NOT NULL,
    CODE_ENTRETIEN VARCHAR(2) NOT NULL,
    DATE_PREVISIONNELLE DATE NOT NULL,
    NATURE_ENTRETIEN VARCHAR(10) NOT NULL,
    NUMERO_ENTRETIEN BIGINT
    );

    ALTER TABLE TB_CALENDRIER ADD CONSTRAINT FK_TB_CALENDRIER_1 FOREIGN KEY (NUMERO_ENTRETIEN) REFERENCES TB_HIS_ENTRETIEN (NUMERO_ENTRETIEN) ON DELETE CASCADE ON UPDATE CASCADE;
    Aussi, j'ai crée deux déclencheurs ; un sur la table tb_Hist_Entretien et un autre sur la table tb_Calendrier.

    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
    CREATE OR ALTER trigger tb_his_entretien_bi for tb_his_entretien
    active before insert or update position 0
    AS
    declare variable V1 varchar(1);
    declare variable V2 varchar(3);
    declare variable V3 varchar(5);
    declare variable cmp smallint;
    declare variable v_num_ods varchar(9);
    declare variable freq varchar(20);
    declare variable p_v2 smallint;
    declare variable v_date_int date;
    declare variable nb_fois smallint;
    declare variable code_org varchar(16);
    declare variable code_entre smallint;
    declare variable date_previs date;
    declare variable n_ordre_entretien smallint;
    BEGIN
      nb_fois = 2;
      IF (NEW.NUMERO_ENTRETIEN IS NULL) THEN
        NEW.NUMERO_ENTRETIEN = GEN_ID(GEN_TB_HIS_MAIN_ID,1);
     
      /* Extraction de l'année */
      V3 = '/' || cast(Extract(year from new.date_inter) as varchar(4));
     
      /* compter le nbr d'enregitrements selon les deux critères */
      select count(oe.code_etretien), max(oe.frequence),
      max(oe.code_organe), max(oe.code_etretien)
       from tb_organe_entretien oe
        where (oe.code_organe = new.code_organe and
               oe.code_etretien = new.code_entretien)
      into :cmp, :freq, :code_org, :code_entre;
     
      /* si choix est CEP (calendrier d'entretin préventif) */
      if (new.cause = 'CEP') then
      begin
        /* si le nombre d'enregistrements est différents de 0  */
        /* donc la table comprend des entretiens */
        if (cmp = 0) then exception Erreur_Entretien_Introuvable;
        /* reseiger dans une variable locale le type d'ODS */
        V1 = 'P';
      end else V1 = 'C';
     
      /* si corredctive alors vérifier la date de la panne */
      if ((new.cause <> 'CEP') and (new.date_panne is null)) then
      exception erreur_date_panne;
     
      if (inserting) then
      begin
        select max(h.n_ods), max(h.date_inter) from tb_his_entretien h
        where (substring(h.n_ods from 1 for 1) =: V1)
        into :v_num_ods,
             :v_date_int;
     
        /* s'assurer de la date entrée */
        if (new.date_inter < v_date_int) then exception erreur_date_courrante;
     
        /* formuler le code de l'ODS */
        V2 = '001';
        if (v_num_ods <> '') then
        begin
          V2 = substring(v_num_ods from 2 for 3);
          p_v2 = cast(v2 as smallint);
          p_v2 = p_v2 + 1;
          V2 = cast(p_v2 as varchar(3));
     
          if (char_length(V2) = 2) then V2 = '0' || V2;
          if (char_length(V2) = 1) then V2 = '00' || V2;
        end
        /* renseigner l'info dans la champ approprié */
        new.n_ods = coalesce(V1,'') || coalesce(V2,'') || coalesce(V3,'');
      end
     
      if (freq = 'MENSUEL') then
      begin
        new.date_prev = dateadd(30 day to new.date_inter);
        nb_fois = 24;
      end
      if (freq = 'TRIMESTRIEL') then
      begin
        new.date_prev = dateadd(91 day to new.date_inter);
        nb_fois = 8;
      end
      if (freq = 'SEMESTRIEL') then
      begin
        new.date_prev = dateadd(182 day to new.date_inter);
        nb_fois =  4;
      end
      if (freq = 'ANNUEL') then new.date_prev = dateadd(365 day to new.date_inter);
     
      date_previs = new.date_prev;
      /* manque test */
      cmp = 0;
      select count(*) from tb_calendrier cc
      where (cc.code_organe = :code_org)
      into :cmp;
     
      if (nb_fois <> cmp) then
      begin
        n_ordre_entretien = 1;
        while (nb_fois >= 1) do
        begin
          insert into tb_calendrier (code_organe, code_entretien, date_previsionnelle)
          values (:code_org, :code_entre,:date_previs);
          if (freq = 'MENSUEL') then date_previs = dateadd(1 month to date_previs);
          if (freq = 'TRIMESTRIEL') then date_previs = dateadd(3 month to date_previs);
          if (freq = 'SEMESTRIEL') then date_previs = dateadd(6 month to date_previs);
          if (freq = 'ANNUEL') then date_previs = dateadd(12 month to date_previs);
          nb_fois = nb_fois - 1;
          n_ordre_entretien = n_ordre_entretien + 1;
        end
      end
    END
    Le seul problème avec ce déclencheur est dans cette partie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    insert into tb_calendrier (code_organe, code_entretien, date_previsionnelle)
          values (:code_org, :code_entre,:date_previs);
    Cette table contient le champ {NUMERO_ENTRETIEN} qui doit être renseigné automatiquement lors d'une insertion dans la table tb_Hist_Entretien, pour cela j'ai dû créer un déclencheur de type After sur la table tb_Calendrier afin de mettre à jour la ligne en cours :
    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
    CREATE OR ALTER trigger tb_calendrier_ai0 for tb_calendrier
    active after insert position 0
    AS
    declare variable c_org varchar(20);
    declare variable c_entretien smallint;
    declare variable d_prev date;
    declare variable n_entretien bigint;
    begin
      select hh.code_organe, hh.code_entretien, hh.numero_entretien, hh.date_prev
      from tb_his_entretien hh
      where (hh.numero_entretien = (select max(hs.numero_entretien) from tb_his_entretien hs))
      into :c_org,
           :c_entretien,
           :n_entretien,
           :d_prev;
     
      update tb_calendrier c set c.numero_entretien = :n_entretien
      where (c.code_organe =:c_org and
      c.code_entretien =:c_entretien and
      c.date_previsionnelle =:d_prev);
    end
    Le problème :
    - Quant j'insère la 1ère ligne dans la table tb_Hist_Entretien, je remarque que le champ {NUMERO_ENTRETIEN} de la table tb_Calendrier prend la valeur Null;
    - Au delà de la 1ère ligne, le champ {NUMERO_ENTRETIEN} prend une valeur n-1 ? comme si, la nouvelle ligne n'a pas subit de commit et n'est pas visible par la base de données c'est pourquoi cette valeur null quand j'insère la 1ère ligne.

    Je voudrais savoir s'il est possible de forcer le commit avant l'appel du déclencheur tb_calendrier_ai0 ?
    S'il est possible de faire plus simple je suis aussi preneur.

    Merci à tous....
    Bon courage ou Bonne Chance (selon le contexte)
    Mon blog sur WordPress

  2. #2
    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 Erreur fatale de ma part !!
    Re tout le monde.
    Je viens de trouver mon erreur, en fait il s'agissait d'un mauvais appel à un déclencheur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    IF (NEW.NUMERO_ENTRETIEN IS NULL) THEN
        NEW.NUMERO_ENTRETIEN = GEN_ID(GEN_TB_HIS_MAIN_ID,1);
    j'avais deux déclencheurs qui se ressemblaient et je faisais appel au mauvais, je viens de corriger tout est rentré dans l'ordre.
    Bon courage ou Bonne Chance (selon le contexte)
    Mon blog sur WordPress

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

Discussions similaires

  1. Relation père / fils sur une même table
    Par useramina dans le forum JPA
    Réponses: 0
    Dernier message: 03/05/2009, 13h44
  2. [Mapping] Relation père fils sur une même table.
    Par Invité dans le forum Hibernate
    Réponses: 1
    Dernier message: 11/06/2008, 17h14
  3. mise à jour avec une relation 1-N
    Par gendalf37400 dans le forum Ruby on Rails
    Réponses: 4
    Dernier message: 14/06/2007, 18h08
  4. Table avec lignes ayant une relation "père-fils"
    Par the java lover dans le forum Windows Forms
    Réponses: 7
    Dernier message: 02/04/2007, 11h20
  5. Mise à jour d'une table avec un fichier csv
    Par blackangel dans le forum PostgreSQL
    Réponses: 4
    Dernier message: 26/05/2005, 14h46

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