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

PL/SQL Oracle Discussion :

Integrité referentiel appliqué par un trigger, recuperation des rejets associés


Sujet :

PL/SQL Oracle

  1. #1
    Candidat au Club
    Inscrit en
    Septembre 2007
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Septembre 2007
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Integrité referentiel appliqué par un trigger, recuperation des rejets associés
    Nous tentons d'appliquer une integrité referentiel entre deux tables (CNT et CNU).
    un enregistrement CNU(contrat unitaire) peut etre inserer si l'on trouve son contrat (CNT).
    pour cela, nous utilisons un trigger.
    il est declarer de la sorte et appliquer sur la table cible (CNU):

    CREATE OR REPLACE TRIGGER CNU_CONTROLE_CNT
    BEFORE INSERT ON CNU_CONTRAT_UNITAIRE
    REFERENCING NEW AS NEW OLD AS OLD
    FOR EACH ROW
    DECLARE
    trouver NUMBER:=0 ;

    BEGIN
    -- vérifivation de la présence du contrat actif

    SELECT COUNT(*) INTO trouver
    FROM CNT_CONTRAT a
    WHERE :new.CNT_CODE = a.CNT_CODE
    AND :new.CNU_INV_DEB >= a.CNT_INV_DEB
    and :new.CNU_INV_DEB < a.CNT_INV_FIN
    ;
    IF trouver <> 0 THEN
    RAISE_APPLICATION_ERROR(-00001,'NAME: Pas de contrat valide dans la table CNT_CONTRAT //END');
    END IF;

    END CNU_CONTROLE_CNT;
    /


    Nous nous attendons donc a recuperer les enregistrement rejetés par le trigger (on attend un fonctionnement identique a un rejet sur une PK/FK).
    Cependant, le programme effectuant les insert passe en Failed dès qu'on 'tombe' sur un enregistrement ne respectant pas le trigger.
    le message d'erreur envoyé est le suivant:

    Severity Timestamp Node Thread Message Code Message
    ERROR 11/09/2007 17:31:07 node01_rs39 WRITER_1_*_1 WRT_8229 Database errors occurred:
    ORA-20011: NAME: Pas de contrat valide dans la table CNT_CONTRAT //END
    ORA-06512: à "XOB.CNU_CONTROLE_CNT", ligne 14
    ORA-04088: erreur lors d'exécution du déclencheur 'XOB.CNU_CONTROLE_CNT'

    Comment peut on contourner le 'Failed' et recuperer les rejets associés au trigger?

  2. #2
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    pourquoi réinventé la roue?

    Oracle a des contraintes d'inégrités référentielles bien plus efficaces qu'un trigger maison.

    Quant à récupérer les enregistrements rejettés, il suffit de faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into t values (blabla) log errors ;
    Merci de toujours préciser ta version

  3. #3
    Candidat au Club
    Inscrit en
    Septembre 2007
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Septembre 2007
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Il est vrai qu'il est inutile de reinventer la roue!
    le souci qui se pose est que l'on utilise un ETL, Informatica Powercenter pour charger dans les tables nos enregistrements.
    Ainsi, quand oracle rejete un enregistrement pour contrainte d'integrité ou autre, nous avons le moyen de les recuperer.
    Nous souhaitons alors appliquer une nouvelle contrainte referentiel (lié a une table 'mère'->un CNU ne peut etre inserer si le CNT n'existe pas).
    L'idée est alors de laisser oracle géré le rejet lié a cette contrainte.
    nous pensions qu'il rejeterait l'enregistrement 'normalement' (comme il peut le fait sur une contrainte d'integrité).

    l'usage du trigger nous semble plus 'confortable' car ce type de contrainte d'integrité est a appliquer sur d'autres tables (suivant le meme principe: une table mère/une table fille, on insert dans la fille uniquement si on trouve la clé dans la mere).

    Comment peut on lever un warning dans un trigger?
    ce pourrait etre la solution... dans notre trigger on leve un erreur qui fait 'planter' l'application RAISE_APPLICATION_ERROR.
    Si on utilise un 'raise_warning' l'application continuerait probablement son travail...

    la version d'oracle utilisé est la 10g

  4. #4
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    je n'aime pas trop les triggers, c'est moins fiable que les contraintes.

  5. #5
    Candidat au Club
    Inscrit en
    Septembre 2007
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Septembre 2007
    Messages : 3
    Points : 2
    Points
    2
    Par défaut [RESOLU]
    Exact, les contraintes c'est meilleur!!!
    la ruse est de modifier l'enregistrement a inserer pour qu'il soit rejeté par une contrainte existante(on ne peut pas ajouter de contrainte sur les tables).
    Ainsi, nous avons un champ (que l'on renseigne toujours) qui doit etre non null.
    nous nous servons de cette contrainte pour effectuer notre rejet dans notre trigger.
    il suffit de mettre a null le champ lorque l'on tente d'inserer un enregistrement n'ayant pas de contrat CNU.

    voici le code

    CREATE OR REPLACE TRIGGER CNU_CONTROLE_CNT
    BEFORE INSERT ON CNU_CONTRAT_UNITAIRE
    REFERENCING NEW AS NEW OLD AS OLD
    FOR EACH ROW
    DECLARE
    trouver NUMBER:=0 ;

    BEGIN
    -- vérifivation de la présence du contrat actif

    SELECT COUNT(*) INTO trouver
    FROM CNT_CONTRAT a
    WHERE :new.CNT_CODE = a.CNT_CODE
    AND :new.CNU_INV_DEB >= a.CNT_INV_DEB
    and :new.CNU_INV_DEB < a.CNT_INV_FIN
    ;
    IF trouver=0 THEN
    :new.CNU_INV_FIN := NULL;
    END IF;

    END CNU_CONTROLE_CNT;
    /


    Merci pour ton aide...ca m'a mis sur la bonne piste!

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 10/05/2007, 13h55
  2. recuperation des lignes commencant par -
    Par vince2005 dans le forum Langage
    Réponses: 1
    Dernier message: 24/04/2007, 15h55
  3. [vb6] recuperation des champs par un listbox
    Par lumbroso dans le forum VB 6 et antérieur
    Réponses: 14
    Dernier message: 22/08/2006, 11h41
  4. trigger d'integrite referentielle
    Par david42 dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 30/05/2006, 13h23
  5. Recuperation des valeurs envoyé par PTRACE
    Par dragonfly dans le forum Linux
    Réponses: 8
    Dernier message: 23/01/2006, 18h21

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