Forum APEX - Développement Oracle Application Express

Le site des développeurs francophones APEX - Oracle Application Express

Vous n'êtes pas identifié(e).

Annonce

Bienvenue sur le forum Oracle APEX

S'il s'agit de votre première visite, nous vous invitons à consulter la FAQ en cliquant sur le lien ci-dessous. Vous pouvez poster ici toutes vos questions sur l'installation, le développement (composants clients et serveurs), l'administration des instances Oracle APEX. Par ailleurs, ce forum diffuse les annonces et actualités relatives à Oracle APEX.

Oracle APEX 4.1

Oracle APEX 4.1 est disponible depuis le 24 août 2011.

Oracle APEX 4.0

Oracle APEX 4.0 est disponible depuis le 23 juin 2010. Il existe 2 distributions, une distribution en langue anglaise uniquement et une distribution multilingue.

#1 2011-07-13 20:31:21

thomasx25
Membre
Inscription : 2011-07-12
Messages : 4

Créer un panneau avec interrogation SQL(extraire une ligne)

Bonjour,
je cherche une âme charitable pour m'éclairer, je cherche via un panneau à insérer des valeurs sur 3 tables.
J'utilise bien la fonction  interrogation SQL(extraire une ligne).
Ensuite,je crée  mes éléments manuellement. l'insertion des valeurs dans les tables ne se font pas. Quels processus et/ou validations dois-je rajouter?
Aucun exemple sur cette fonction est disponible dans le livre Achène Bourouis.

Je vous communique ma requête:
     SELECT   E.NUM_ENTRP ,     E.TITRE,  E.NOM_ENTRP,  E.TEL_ENTRP,  E.TELECOPIE_ENTREPRISE,  E.EMAIL_ENTREPRISE, E.REMARQUES_ENTREPRISE,
                  A.ID_ADRESSE,  A.CD_TYP_ADR ,   A.CD_INSEE  ,A.LIGNE1_ADRESSE  ,A.LIGNE_LIGNE2_ADRESSE,  A.LIGNE3_ADRESSE,
                  C.NUM_ENTRP ,C.ID_ADRESSE
     FROM     ENTREPRISES E ,ADRESSES A, CLIENTADRES C
    WHERE  A.ID_ADRESSE=C.ID_ADRESSE
       AND    E.NUM_ENTRP=C.NUM_ENTRP

merci d'avance.
       

version Oracle Database 10g Express Edition Release 10.2.0.1.0

Hors ligne

#2 2011-07-14 22:36:09

admin
Administrateur
Inscription : 2010-08-02
Messages : 83

Re : Créer un panneau avec interrogation SQL(extraire une ligne)

Bonjour thomasx25,
Tu ne peux pas mettre a jour 3 tables avec un panneau base sur le composant d'extraction ou de mise a jour. Pour utiliser ces composants il faut creer une vue updatable sur tes 3 tables sinon creer manuellement un panneau et ajouter un processus plsql avant affichage des regions pour extraire des lignes de tables et code un processus plsql apres soumission pour mettre a jour tes tables.

Donnes nous plus d'elements, on te proposera un exemple de code.

Hors ligne

#3 2011-07-16 15:03:59

thomasx25
Membre
Inscription : 2011-07-12
Messages : 4

Re : Créer un panneau avec interrogation SQL(extraire une ligne)

Bonjour et merci pour ton aide.
mon MCD me donne deux entités "entreprises" et "adresses", le lien étant l' association "clientadres".
Une entreprise possède 1 à n adresses.
une adresse appartient 0 à n entreprises.

ENTREPRISES(NUM_ENTRP<pk>,NUMERO_CONTRAT_INFO<fk>,TITRE, NOM_ENTRP,TEL_ENTRP,TELECOPIE_ENTREPRISE,EMAIL_ENTREPRISE,...)

ADRESSES(ID_ADRESSE<pk>,CD_TYP_ADR<fk2>,CD_INSEE<fk1>,LIGNE1_ADRESSE,LIGNE2_ADRESSE,LIGNE3_ADRESSE)

CLIENTADRES(NUM_ENTRP<pk,fk2>,ID_ADRESSE<pk,fk1>)


J'ai une séquence pour les clés primaires de la table ENTREPRISES et ADRESSES.
J'aimerai un panneau ou pourquoi pas 3 panneaux (ENTREPRISES, ADRESSES LIVRAISON, ADRESSES FACTURATION) mais comment gérer les clés
primaires?: ENTREPRISES.NUM_ENTRP=CLIENTADRES.NUM_ENTRP
            ADRESSES.ID_ADRESSE=CLIENTADRES.ID_ADRESSE

En attente d'un exemple de code





Mon MCD:je donne le lien direct: http://img199.imageshack.us/img199/3133/final1e.png

FluxBB bbcode test


Une vue des éléments: http://img196.imageshack.us/img196/5774 … eadrec.png

Dernière modification par thomasx25 (2011-07-24 10:11:47)

Hors ligne

#4 2011-07-18 13:16:42

admin
Administrateur
Inscription : 2010-08-02
Messages : 83

Re : Créer un panneau avec interrogation SQL(extraire une ligne)

Bonjour Thomasx25,

Dans ton cas, il n'est pas possible d'utiliser une vue updatable pour la raison suivante, au moment de l'insert le moteur SQL ne connait pas la clef à ajouter à la colonne Pk de la table CLIENTADRES.
On va donc créer une page avec un panneau, voici un exemple qui te permettra de gérer l'ajout et la mise à jour de plusieurs tables dans une page avec une région de type panneau table.

Pour faciliter la compréhension, je ne déclare que quelques colonnes et leurs éléments de page.

On suppose que l'on arrive à cette page avec un passage de 2 paramètres :P2_NUM_ENTRP et :P2_ID_ADRESSE.
Si ces 2 paramètres ne sont pas nuls, il s'agit donc d'une mise à jour dans le cas contraire, nous ajouterons ces données dans les tables
respectives.

La méthode décrite ci-dessous repose sur l'utilisation d'un processus PL/SQL avant affichage de la page pour extraire les données s'il s'agit
d'une mise à jour et sur un processus PL/SQL après soumission pour mettre à jour les tables (soi en ajout soit en mise à jour).

Bien entendu, l'ajout de validations permettra de vérifier la saisie d' utilisateur avant d'effectuer les opérations d'ajout/mise à jour.
--------------------------------------------------------------------------------------------------------------------------
--
-- Création de la page avec le panneau
--
Créons une page que l'on appelle page 2
    Créons une région de type panneau sur une table
    ajoutons les éléments de page suivants de type Textfield:
   
    P2_NOM_ENTRP, 
    P2_TEL_ENTRP, 
    P2_CD_TYP_ADR,   
    P2_CD_INSEE
   
    ajoutons les éléments de pages suivants de type Masqué.

    P2_NUM_ENTRP
    P2_ID_ADRESSE
--------------------------------------------------------------------------------------------------------------------------   
--
--  Ajoutons un processus PL/SQL après entête
--
  A partir de la page à traiter,
    Cliquez sur ajouter un processus PL/SQL
      Point - evenement de chargement après en-tête
     
      declare
      cursor c is  SELECT   E.NUM_ENTRP ,     E.TITRE,  E.NOM_ENTRP,  E.TEL_ENTRP,  E.TELECOPIE_ENTREPRISE,  E.EMAIL_ENTREPRISE,
        E.REMARQUES_ENTREPRISE, A.ID_ADRESSE,  A.CD_TYP_ADR ,   A.CD_INSEE  ,A.LIGNE1_ADRESSE  ,A.LIGNE_LIGNE2_ADRESSE, 
        A.LIGNE3_ADRESSE, C.NUM_ENTRP ,C.ID_ADRESSE
        FROM     ENTREPRISES E ,ADRESSES A, CLIENTADRES C
        WHERE  A.ID_ADRESSE=C.ID_ADRESSE
        AND    E.NUM_ENTRP=C.NUM_ENTRP;
       
      begin
        for m in c loop

        :P2_NOM_ENTRP  :=  m.NOM_ENTRP;
        :P2_TEL_ENTRP   :=  m.TEL_ENTRP;
        :P2_CD_TYP_ADR :=  m.CD_TYP_ADR;
        :P2_CD_INSEE     :=  m.CD_INSEE;

        end loop;
      end;           
   

Conditions d'exécution
  Corps de fonction PL/SQL renvoyant une valeur booléenne
  Expression 1 =     
  if :P2_NUM_ENTRP is not null and :P2_ID_ADRESSE is not null then
    return true;
  end if;

--------------------------------------------------------------------------------------------------------------------------   
--
--  Ajouter un processus PL/SQL après soumission de la page
--   
declare
    v_NUM_ENTRP   number;
    v_ID_ADRESSE  number;     

begin

  if :P2_NUM_ENTRP is not null and :P2_ID_ADRESSE is not null then
    insert into ENTREPRISES (NOM_ENTRP, TEL_ENTRP) VALUES (:P2_NOM_ENTRP, :P2_TEL_ENTRP) returning ID_ENT into vNUM_ENTRP;

    insert into ADRESSES (CD_TYP_ADR, CD_INSEE) VALUES (:P2_CD_TYP_ADR, :P2_CD_INSEE) returning ID_ADR into v_ID_ADRESSE;
   
    insert into CLIENTADRES (NUM_ENTRP, ID_ADRESSE) VALUES(v_NUM_ENTRP, v_ID_ADRESSE);
  else

    update ENTREPRISES set NOM_ENTRP = :P2_NOM_ENTRP, TEL_ENTRP = :P2_TEL_ENTRP  where NUM_ENTRP = :P_NUM_ENTR;

    update ADRESSES    set CD_TYP_ADR = :P2_CD_TYP_ADR, CD_INSEE = :P2_CD_INSEE  where ID_ADRESSE = :P_ID_ADR;

  end if;   
-- même si APEX effectue automatique un commit, j'en rajoute toujours un.
  commit;

end;
--------------------------------------------------------------------------------------------------------------------------
--
--  Ajouter une validation globale pour vérifier la saisie de l'utilisateur.
-- 
    ajouter une validation
      Validation de Niveau page
        Méthode de validation PL/SQL
          Type de validation : Fonction renvoyant un texte d'erreur
         
          exemple de code :
         
          if P2_NOM_ENTRP is  null then
            return 'Renseignez le nom !';
          else
             return null;
          end if;
--------------------------------------------------------------------------------------------------------------------------
Pour le passage de paramètres à la page 2, utilises un branchement en configurant les attributs :
- Définir ces éléménts : P2_NUM_ENTRP, P2_ID_ADRESSE
- avec ces valeurs : &P2_NUM_ENTRP., &P2_ID_ADRESSE.

Hors ligne

#5 2011-07-20 21:08:40

thomasx25
Membre
Inscription : 2011-07-12
Messages : 4

Re : Créer un panneau avec interrogation SQL(extraire une ligne)

Bonjour Admin,
je reviens vers toi, j'ai bien compris le principe des 2 processus.
Mais après correction de quelques coquilles, j' ai un message d'erreur sur ce deuxième.
J'ai essayé de modifier celui-ci, sans succés(ne manque-t-il pas un begin et un select?). Le processus est en fin page.

FluxBB bbcode test









declare
    v_NUM_ENTRP   number;
    v_ID_ADRESSE  number;     

  if :P3_NUM_ENTRP is not null and :P3_ID_ADRESSE is not null then
    insert into ENTREPRISES (NOM_ENTRP, TEL_ENTRP) VALUES (:P3_NOM_ENTRP, :P3_TEL_ENTRP) returning NUM_ENTRP into v_NUM_ENTRP;

    insert into ADRESSES (CD_TYP_ADR, CD_INSEE) VALUES (:P3_CD_TYP_ADR, :P3_CD_INSEE) returning ID_ADRESSE into v_ID_ADRESSE;
   
    insert into CLIENTADRES (1, 2) VALUES(v_NUM_ENTRP, v_ID_ADRESSE);
  else

    update into ENTREPRISES set NOM_ENTRP = :P3_NOM_ENTRP, TEL_ENTRP = :P3_TEL_ENTRP  where NUM_ENTRP = :P3_NUM_ENTRP;

    update into ADRESSES    set CD_TYP_ADR = :P3_CD_TYP_ADR, CD_INSEE = :P3_CD_INSEE  where ID_ADRESSE = :P3_ID_ADRESSE;

  end if;   

  commit;




--merci pour ton aide.

Dernière modification par thomasx25 (2011-07-20 21:12:10)

Hors ligne

#6 2011-07-25 12:41:17

admin
Administrateur
Inscription : 2010-08-02
Messages : 83

Re : Créer un panneau avec interrogation SQL(extraire une ligne)

Bonjour,

J'ai corrigé le code PL/SQL dans ma précédente réponse, je t'avais envoyé cette réponse dans le train à partir de mon iPhone );.

Pour information, un processus PL/SQL à l'intérieur d'une page APEX accepte des expressions PL/SQL sans declare-begin-end.

Pour le reste, il obéit à la syntaxe d'un bloc PL/SQL anonyme.

Hors ligne

#7 2011-08-03 21:56:25

thomasx25
Membre
Inscription : 2011-07-12
Messages : 4

Re : Créer un panneau avec interrogation SQL(extraire une ligne)

Bonjour Admin, de nouveau bloqué, je me permets de te solliciter.

L'insert des données sur les 3 tables lors d'une création fonctionne.

Par contre lors d'un update, je rencontre 2 problèmes:
je passe par une région état(page1), j'ai crée un lien de colonne sur un attribut (ID_ADRESSE) renvoyant les clés primaires sur les éléments
P2_ID_ADRESSE et P2_NUM_ENTRP .Les clés primaires sont bien affichés lors du passage à la page2.


J'ai bien crée un processus Aprés en-tête dont voici le code simplifié:

declare
      cursor c is  SELECT   E.NOM_ENTRP, E.TITRE,E.TEL_ENTRP,       E.TELECOPIE_ENTREPRISE,  E.EMAIL_ENTREPRISE,
        E.REMARQUES_ENTREPRISE,A.CD_TYP_ADR ,A.CD_INSEE, A.LIGNE1_ADRESSE  ,A.LIGNE_LIGNE2_ADRESSE,A.LIGNE3_ADRESSE
       
        FROM     ENTREPRISES E ,ADRESSES A, CLIENTADRES C
        WHERE  A.ID_ADRESSE=C.ID_ADRESSE
        AND    E.NUM_ENTRP=C.NUM_ENTRP
         AND    :P2_NUM_ENTRP=E.NUM_ENTRP
        AND    :P2_ID_ADRESSE=A.ID_ADRESSE
    ;
       
      begin
        for m in c loop
        :P2_NOM_ENTRP  :=  m.NOM_ENTRP;
        :P2_TEL_ENTRP   :=  m.TEL_ENTRP;
        :P2_CD_TYP_ADR :=  m.CD_TYP_ADR;
        :P2_CD_INSEE     :=  m.CD_INSEE;
       
       
        end loop;
      end;



le champs des éléments reste null malgré des valeurs saisies lors de la création (mon premier problème).
Si malgré tout, je valide l'update (bouton "appliquer les modifications"), Oracle me renvoit:

ORA-02292: violation de contrainte (THOMAS.FK_CLIENTAD_CLIENTADR_ENTREPRI) d'intégrité - enregistrement fils existant


J'ai modifié les clés étrangères:
         ALTER TABLE CLIENTADRES ADD (
         CONSTRAINT FK_CLIENTAD_CLIENTADR_ADRESSES CHECK (ID_ADRESSE IS NOT NULL)
         DEFERRABLE INITIALLY DEFERRED);

Je n'ai plus de message d'erreur;

L'update ne se fait toujours pas.
Je pense que le  problème vient du bouton "appliquerles modifications" (Action SQL UPDATE), il valide
l 'update que de la table ENTREPRISES (oracle crée une nouvelle ligne avec une clé primaire<>).
D'où ma question,  Comment créer un bouton de fonction SQL UPDATE qui me permet de valider la mise à jour de mes tables?


declare
    v_NUM_ENTRP   number;
    v_ID_ADRESSE  number;     

  if :P2_NUM_ENTRP is null and :P2_ID_ADRESSE is null then
    insert into ENTREPRISES (NOM_ENTRP, TEL_ENTRP) VALUES (:P2_NOM_ENTRP, :P2_TEL_ENTRP) returning NUM_ENTRP into v_NUM_ENTRP;

    insert into ADRESSES (CD_TYP_ADR, CD_INSEE) VALUES (:P2_CD_TYP_ADR, :P2_CD_INSEE) returning ID_ADRESSE into v_ID_ADRESSE;
   
    insert into CLIENTADRES (NUM_ENTRP, ID_ADRESSE) VALUES(v_NUM_ENTRP, v_ID_ADRESSE);
  else

    update into ENTREPRISES set NOM_ENTRP = :P2_NOM_ENTRP, TEL_ENTRP = :P2_TEL_ENTRP  where NUM_ENTRP = :P2_NUM_ENTRP;

    update into ADRESSES    set CD_TYP_ADR = :P2_CD_TYP_ADR, CD_INSEE = :P2_CD_INSEE  where ID_ADRESSE = :P2_ID_ADRESSE;

  end if;   

  commit;

Dernière modification par thomasx25 (2011-08-03 22:05:15)

Hors ligne

#8 2011-08-05 08:52:05

admin
Administrateur
Inscription : 2010-08-02
Messages : 83

Re : Créer un panneau avec interrogation SQL(extraire une ligne)

Bonjour Thomasx25,

3 causes possibles peuvent être à l'origine de ton problème :

1) Le type d'élément de page qui reçoit les valeurs de P2_TEL_ENTRP et P2_ID_ADRESSE :
    Si tu as créé des éléments de type hidden , précise bien No à la propriété "Value protected"
    Si tu as créé des éléments de type Display only, précise bien Yes à la propriété "Save Session State"

2)  Une erreur de frappe produit un nom d'élément différent que le moteur APEX ne détecte pas, assure toi que chaque élément de page utilisé dans
    ton bloc PL/SQL correspond bien à un élément de page défini dans ta page.


3)  Si la page reçoit les bonnes valeurs mais ne les affiche pas dans les champs prévus, l'erreur provient de l'extraction (cursor is select / boucle for m in c).

    Il faut tester ton select défini dans ton curseur PL/SQL dans une fenêtre SQL d'APEX ou de SQL Developer pour vérifier qu'il te retourne bien une ligne.

        SELECT   E.NOM_ENTRP, E.TITRE,E.TEL_ENTRP,       E.TELECOPIE_ENTREPRISE,  E.EMAIL_ENTREPRISE,
                E.REMARQUES_ENTREPRISE,A.CD_TYP_ADR ,A.CD_INSEE, A.LIGNE1_ADRESSE  ,A.LIGNE_LIGNE2_ADRESSE,A.LIGNE3_ADRESSE
               
                FROM     ENTREPRISES E ,ADRESSES A, CLIENTADRES C
                WHERE  A.ID_ADRESSE=C.ID_ADRESSE
                AND    E.NUM_ENTRP=C.NUM_ENTRP
                 AND    :P2_NUM_ENTRP=E.NUM_ENTRP
                AND    :P2_ID_ADRESSE=A.ID_ADRESSE;
       

Pour répondre précisement à ta question, ton bouton doit avoir la valeur No database action pour la propriété "Database action",
on traite manuellement les ordre DML (insert, update), on utilise aucun composant natif apex.

Hors ligne

#9 2011-09-05 23:41:03

ic4it
Membre
Lieu : Grasse
Inscription : 2011-09-05
Messages : 2
Site Web

Re : Créer un panneau avec interrogation SQL(extraire une ligne)

Bonsoir,
tout cela semble bien compliqué et surtout manque à mon avis de "design" de base de données.

1 -  pk ID_ADRESSE de la table partagée entres clients et fournisseurs et techniciens :
on crée une séquence SEQ_ID_ADRESSE puis un trigger before insert sur la table qui mets à jour cet ID.

2- pourquoi vouloir tout faire en une seule opération ? Un client = plusieurs adresses non ?

je verrais plutôt ça comme ça...

déjà ton select
SELECT   E.NUM_ENTRP ,     E.TITRE,  E.NOM_ENTRP,  E.TEL_ENTRP,  E.TELECOPIE_ENTREPRISE,  E.EMAIL_ENTREPRISE, E.REMARQUES_ENTREPRISE,
                  A.ID_ADRESSE,  A.CD_TYP_ADR ,   A.CD_INSEE  ,A.LIGNE1_ADRESSE  ,A.LIGNE_LIGNE2_ADRESSE,  A.LIGNE3_ADRESSE,
                  C.NUM_ENTRP ,C.ID_ADRESSE
     FROM     ENTREPRISES E ,ADRESSES A, CLIENTADRES C
    WHERE  A.ID_ADRESSE=C.ID_ADRESSE
       AND    E.NUM_ENTRP=C.NUM_ENTRP

qu'est ce qui se passe si une entreprise n'a pas d'adresse de déclarée ? ben tu vas passer à côté (pas de jointure externe) et donc tu risque de recréer la même ....

je ferais un IR (interactive report) avec la liste des entreprises et adresses basée sur une vue. de là je brancherais un formulaire de modification / création du client et un autre pour les adresses .

tu pourras ainsi créer de nouveaux clients sans avoir à te soucier de renseigner l'adresse de suite et de même tu pourras enrichir un client existant de nouvelles adresses sans passer par ta euh mécanique .....

3- declare
    v_NUM_ENTRP   number;
    v_ID_ADRESSE  number;     

  if :P2_NUM_ENTRP is null and :P2_ID_ADRESSE is null then
    insert into ENTREPRISES (NOM_ENTRP, TEL_ENTRP) VALUES (:P2_NOM_ENTRP, :P2_TEL_ENTRP) returning NUM_ENTRP into v_NUM_ENTRP;

    insert into ADRESSES (CD_TYP_ADR, CD_INSEE) VALUES (:P2_CD_TYP_ADR, :P2_CD_INSEE) returning ID_ADRESSE into v_ID_ADRESSE;
   
    insert into CLIENTADRES (NUM_ENTRP, ID_ADRESSE) VALUES(v_NUM_ENTRP, v_ID_ADRESSE);
  else

    update into ENTREPRISES set NOM_ENTRP = :P2_NOM_ENTRP, TEL_ENTRP = :P2_TEL_ENTRP  where NUM_ENTRP = :P2_NUM_ENTRP;

    update into ADRESSES    set CD_TYP_ADR = :P2_CD_TYP_ADR, CD_INSEE = :P2_CD_INSEE  where ID_ADRESSE = :P2_ID_ADRESSE;

  end if;   

  commit;

là tu cours à la catastrophe tôt ou tard (et plutôt tôt que tard....)
insert ...... pas d'exception de gérée  (ORA-02292: violation de contrainte (THOMAS.FK_CLIENTAD_CLIENTADR_ENTREPRI) d'intégrité - enregistrement fils existant)
...else update....

ça ne passe pas alors on commence à modifier les contraintes d'intégrité , pas bon pas bon du tout.....

plutôt que d'écrire tout le pl/sql dans apex comme tu as fait je prendrais le temps d'écrire une vrai procédure stockée avec gestion des exceptions et tout et tout.

Ce ne sont que quelques pistes écrites vite fait, je ne suis pas un spécialiste apex, par contre en design d'applis et sur oracle j'ai plus de 10ans d'expérience.

N'hésite pas si tu veux approfondir le sujet et voir d'autres pistes (basée sur une vue et trigger instead of par ex)

Cordialement
JeanYves

Hors ligne

Pied de page des forums