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

Oracle Discussion :

[FORMS] Gestion d'exception sur une contrainte de type FK


Sujet :

Oracle

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 9
    Points : 2
    Points
    2
    Par défaut [FORMS] Gestion d'exception sur une contrainte de type FK
    Bonjour,

    Sous Forms j'ai un bloc basé sur une table contenant des intégrités référentielle.

    Lorsque je supprime un enregistrement, je voudrais pouvoir gérer l'erreur du a la contrainte de l'intégrité référentiel.

    Le problème c'est que Forms n'a pas l'air de voir que l'erreur est du a une contrainte d'intégrité référentiel.

    j'ai le message : 'Suppression (DELETE) d'enregistrement impossible (FRM-40510)' qui est message plutôt générique.

    D'ailleurs cette erreur ne se déclenche pas au moment du delete_record mais du commit qui suit.

    En SQL, lorsque je veux tenter de supprimer une ligne de cette table j'ai bien l"erreur attendu :

    ORA-02292: intergrity constaint (....) violated - Child REcord Found.


    Y'a t'il un moyen que l'erreur ORA-02292 attendu soit visible par Forms?

    Ou y'a t'il un moyen de vérifier l'intégrité référentiel avant de faire le delete_record?

    Merci

  2. #2
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Tu as le Trigger de Form ON-ERROR
    Voici un exemple
    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
    DECLARE 
     
      v_errcod  		NUMBER			:= DBMS_ERROR_CODE; 
      v_errtxt  		VARCHAR2 (200) 	:= DBMS_ERROR_TEXT; 
     
      errnum NUMBER       := ERROR_CODE; 
      errtxt VARCHAR2(80) := ERROR_TEXT; 
      errtyp VARCHAR2(3)  := ERROR_TYPE; 
     
    BEGIN 
     
    	-- Si on a le message : 'ORA-01407: impossible de mettre à jour (IDRELATION") avec NULL'
    	IF (v_errcod = -1407)
    	THEN 
     
    		message('PAS POSSIBLE');
     
    	ELSE
    	  Message(errtyp||'-'||TO_CHAR(errnum)||': '||errtxt); 
        RAISE Form_Trigger_Failure; 
    	END IF; 
    END;

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    Je sais ou et comment attraper une exception.

    Le souci c'est que ce n'est pas la bonne exception qui se déclenche.

    On a un FRM-40510 plutôt générique (Delete impossible) alors que l'exception ORA-02292, elle ne se déclenche pas (intergrity constaint violated - Child Record Found. )

    Y'a t'il un moyen d'avoir cette erreur visible sous forms?

  4. #4
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Regarde dans les paramètres de ta relation Maitre-Détail (Option Delete Record behavior) Tu dois avoir Non Isolated, forms le gère automatiquement (avant les triggers)

    Setting Description
    Non-Isolated
    The default setting. Prevents the deletion of a master record when associated detail records exist in the database.

    Isolated
    Allows the master record to be deleted and does not affect associated detail records in the database.

    Cascading
    Allows the master record to be deleted and automatically deletes any associated detail records in the detail block's base table at commit time. In a master-detail-detail relation, where relations are nested, only records in the immediate detail block are deleted (deletions do not cascade to multiple levels of a relation chain automatically).
    Essaie de mettre Isolated et de gérer l'exception dans le ON-ERROR

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    Mais je ne suis pas dans un block maitre-détail.

    Je suis dans un block simple qui est basé sur une table sur laquelles pointes des clés étrangères.

    Sous SQL, la bonn exception se déclenche, pas sous forms...

    Y'a t'il un moyen?

  6. #6
    Membre éprouvé Avatar de star
    Homme Profil pro
    .
    Inscrit en
    Février 2004
    Messages
    906
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Corée Du Nord

    Informations professionnelles :
    Activité : .

    Informations forums :
    Inscription : Février 2004
    Messages : 906
    Points : 1 075
    Points
    1 075
    Par défaut
    Ou y'a t'il un moyen de vérifier l'intégrité référentiel avant de faire le delete_record?
    Juste avant tu codes un select ou un curseur pour voir si le tuple est utilisé comme référence dans tes tables. Je vois bien le code dans le déclencheur key-delrec.
    Y'a t'il un moyen que l'erreur ORA-02292 attendu soit visible par Forms?
    Autrement, remplace l'ordre delete implicite de Forms on codant le déclencheur on-delete, là tu pourras gérer l'erreur dans une exception qui va bien.
    .

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    Le problème c'est que je dois faire ca d'une manière générique pour inclure ca dans KEY-DELREC ou le ON-ERROR de la form de référence pour l'avoir dans toutes l'appli.

    je ne peux donc pas écrire un delete à la main je pense.

    J'ai trouvé sur un forum italien une personne qui apparament a eu exactement le même problème que moi et qui apprament à réussi à le régler en faisant du dynamique avec du DBMS:

    http://www.oracleportal.it/oipforum/...=2241&tstart=0

    Ne parlant pas italien c'est pas super évident... je vais donc regarder du coté du dbms.

  8. #8
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Finkel
    Je sais ou et comment attraper une exception.

    Le souci c'est que ce n'est pas la bonne exception qui se déclenche.

    On a un FRM-40510 plutôt générique (Delete impossible) alors que l'exception ORA-02292, elle ne se déclenche pas (intergrity constaint violated - Child Record Found. )

    Y'a t'il un moyen d'avoir cette erreur visible sous forms?
    J'ai essayé, je catche bien la bonne erreur.
    Trigger ON-ERROR
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    DECLARE 
      v_errcod NUMBER := DBMS_ERROR_CODE; 
    BEGIN
    IF v_errcod = -2292
    THEN
     MESSAGE('DELETE IMPOSSIBLE CHILD TROUVE');
     message(' ');
    END IF;
    END;
    Mais attention, le DELETE_RECORD de FORMS fait ceci :
    - LOCK de la ligne
    - Marquée comme à deleter
    - Effacement de l'affichage

    Forms gère une liste d'enregistrements à DELETER.
    Le delete effectif (en base) ne se fait qu'au COMMIT.

    Est-ce que tu peux faire un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DELETE RECORD; COMMIT_FORM;

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    Si je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            delete_record;
            commit_form;
    alors forms ne vois pas d'erreur oravle : ORA-0000 Sucessfuly completed

    mais se déclenche le FRM-40510.

    Par contre si je fais un :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    delete from stbpays where cod_pays = :blk_maj.cod_pays;
    Alors l'erreur ORA se déclenche bien.


    Je vais modifier le trigger KEY-DELREC qui au moment de la suppresion du record va construire un delete dynamique en mettant dans la clause where tous les champs dont la propriété primary key est à OUI.

    Ca devrais fonctionner comme ca, je vous tiens au courant.

  10. #10
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    VOilà ca fonctionne, j'ai remplacer le delete_record présent dasn le KEY-DELREC par une procédure construisant un Delete en sql.

    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
    123
    124
    PROCEDURE P_delete_record IS
     
    str_cur_blk VARCHAR2(60);-- Le nom du block sur lequel on veut faire un delete
    str_first_itm VARCHAR2(60);-- Le 1er item du block
    str_last_itm VARCHAR2(60);-- Le dernier item du block
    str_cur_itm VARCHAR2(60);-- L'item courant que l'on est en train de lire
    str_pk VARCHAR2(10);-- Variable indiquant si l'item fais partie de la clé primaire
    str_colname VARCHAR2(60);-- Nom de la colonne auquel se réfère l'item
    str_type VARCHAR2(20);-- Type de donné de l'item (char, nimber, etc...)
    str_where VARCHAR2(5000);-- Chaine de carctère dans laquelle on sotcke la clause where
    str_value VARCHAR2(2000);-- Variable stoquant la valeur du champ que l'on est en train de lir
    str_delete VARCHAR2(5000);-- Varaible contenant l'instrucation SQL a executer correspondant au delete
    str_nomtable VARCHAR2(60);-- Le nom de la table sur lequel se réfère le block
    str_typedonne VARCHAR2(30);	-- Type de source de donnée du block (table, procédure, etc...
     
    num_bouton NUMBER;
     
    Exit_Procedure EXCEPTION; 
    Cle_etrangere EXCEPTION;
     
    -- On définie une exception avec le code ORA correspondant
    -- a l'erreur du à l'intégrité référentiel.
    PRAGMA EXCEPTION_INIT(Cle_etrangere, -2292);
     
    BEGIN
     
     
    -- Initialisation des variables
    str_where := '';
    str_nomtable := '';
    str_typedonne := '';
     
    str_cur_blk := :System.Cursor_Block; 
     
    --On repère le 1er item du block et on se positionne dessus
    str_first_itm := Get_Block_Property(str_cur_blk, FIRST_ITEM ); 
    str_last_itm := Get_Block_Property(str_cur_blk, LAST_ITEM ); 
     
    str_cur_itm := str_first_itm;
     
     
    WHILE str_cur_itm != str_last_itm LOOP
     
    -- On regarde si l'item fait partie d'une clé primaire
    str_pk := GET_ITEM_PROPERTY(str_cur_blk||'.'||str_cur_itm,PRIMARY_KEY);
     
    If str_pk = 'TRUE' then
     
    -- On recupère le nom de la colonne associée à l'item (en général identique mais pas toujours)
    str_colname := nvl(GET_ITEM_PROPERTY(str_cur_blk||'.'||str_cur_itm,COLUMN_NAME),str_cur_itm);
     
    -- On récupère le type de variable
    str_type := GET_ITEM_PROPERTY(str_cur_blk||'.'||str_cur_itm,DATATYPE);
     
    If str_type in ('ALPHA', 'CHAR', 'LONG') then
    str_value := ''''||GET_ITEM_PROPERTY(str_cur_blk||'.'||str_cur_itm, DATABASE_VALUE)||'''';
    elsif str_type in ('INT', 'RINT', 'NUMBER', 'RNUMBER', 'MONEY', 'RMONEY') then
    str_value := GET_ITEM_PROPERTY(str_cur_blk||'.'||str_cur_itm, DATABASE_VALUE);
    elsif str_type = 'DATE' then
    str_value := 'to_date('||GET_ITEM_PROPERTY(str_cur_blk||'.'||str_cur_itm, DATABASE_VALUE)||',''DD-MON-YY'')';
    elsif str_type = 'JDATE' then
    str_value := 'to_date('||GET_ITEM_PROPERTY(str_cur_blk||'.'||str_cur_itm, DATABASE_VALUE)||',''MM/DD/YY'')';
    elsif str_type = 'EDATE' then
    str_value := 'to_date('||GET_ITEM_PROPERTY(str_cur_blk||'.'||str_cur_itm, DATABASE_VALUE)||',''DD/MM/YY'')';
    elsif str_type = 'DATETIME' then
    str_value := 'to_date('||GET_ITEM_PROPERTY(str_cur_blk||'.'||str_cur_itm, DATABASE_VALUE)||',''DD-MON-YY HH24:MI:SS'')';
    else
    -- On ne sait pas gérer ce cas type 
    Raise Exit_Procedure;
    end if; 
     
    -- L'item courant faisant partie de la clé primaire (donc basé et non nul) on le rajoute à la clause Where
    str_where := str_where||' AND '||str_colname||' = '||str_value;
     
    End if;
     
    str_cur_itm := GET_ITEM_PROPERTY(str_cur_blk||'.'||str_cur_itm,NEXTITEM);	
     
    END LOOP;
     
    -- Si la chaine where n'est pas vide alors cela veut dire qu'elle commence par un AND qu'on doit enlever
    If str_where is not null then
    str_where := LTRIM(str_where,'AND ');
    end if;
     
    --On récupère le nom de la table sur lequel est basé le block
    str_typedonne := GET_BLOCK_PROPERTY(str_cur_blk, QUERY_DATA_SOURCE_TYPE);
     
    If  str_typedonne = 'TABLE' then
    str_nomtable := GET_BLOCK_PROPERTY(str_cur_blk, QUERY_DATA_SOURCE_NAME);
     
    -- Si le nom de la table est un synonyme, alors on va prendre plutot le nom
    -- de la table en enlevant le 's' devant car le delete sera executé depuis
    -- une procèdure sotckée
    str_nomtable :=  LTRIM(str_nomtable,'s');
     
    end if;
     
    -- Si le block n'est pas basé sur une table
    -- ou si la clause where ne s'est pas construite
    -- (car le block n'a pas de clé primaire défini par exemple)
    -- Alors on ne sais pas gérer le cas
    If str_nomtable is null Or str_where is null then
    Raise Exit_Procedure;
    end if;
     
    -- Construction de la requete
    str_delete := 'delete from '||str_nomtable||' where '||str_where;
     
     
    -- On execute l'instruction SQL a l'aide d'un EXECUTE IMMEDIATE placé en procédure stocké
    sps_com_exec_sql(str_delete);
     
    execute_query;
     
     
    EXCEPTION
    when Cle_etrangere then 
    message('L''enregistrement est référencé');
    raise form_trigger_failure
    --Echec de la tentative de delete, on laisse l'appilcation gérer la suppresion
    when Exit_Procedure then
    delete_record;
    END;

Discussions similaires

  1. Gestion des Callbacks sur une scrolling Bar
    Par neptune2024 dans le forum Interfaces Graphiques
    Réponses: 1
    Dernier message: 22/11/2007, 09h31
  2. exception sur une date
    Par DJERDJAR YACINE dans le forum MS SQL Server
    Réponses: 0
    Dernier message: 30/07/2007, 14h20
  3. Gestion des erreurs sur une commande multiple
    Par domiq44 dans le forum Shell et commandes GNU
    Réponses: 5
    Dernier message: 05/10/2006, 15h03
  4. [excel] Pb de gestion de boutons sur une nouvelle feuille
    Par kenny49 dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 25/08/2006, 18h22
  5. Gestion de pixels sur une BufferedImage
    Par jlassiramzy dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 08/08/2006, 23h02

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