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 :

Script PL/SQL pour effectuer des contrôles de cohérence entre tables.


Sujet :

PL/SQL Oracle

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 31
    Points : 19
    Points
    19
    Par défaut Script PL/SQL pour effectuer des contrôles de cohérence entre tables.
    Bonjour,

    Dans le cadre d'un nettoyage d'une base de données Oracle, je dois effectuer des contrôles de cohérence entre deux tables.
    Un comptage entre deux tables ne suffit pas à affirmer qu’il y a du « un pour un » entre ces deux tables.
    C'est à dire que l’égalité du nombre de postes ne permet pas d’affirmer qu’il s’agit de la même liste de références.
    Par conséquent, il faut bien effectuer les requêtes de sélection en utilisant l'ordre "minus" dans les deux sens.

    Je souhaite également, à la suite de ces requêtes de sélection, mettre à jour un indicateur de cohérence dans une table
    (champ "INDCOHAV" de la table CPT_PURGE).

    Voici le code associé que je cherche à faire:

    Code sql : 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
    -- Codes erreurs Oracle pour quitter le programme des la premiere erreur rencontree
    WHENEVER SQLERROR EXIT 61
    WHENEVER OSERROR  EXIT 62
     
     
    -- Controles INTRA SIG
    -- SIG_RECO05
    -- Mise a jour de l'indice de coherence avant purge
    DECLARE
    nbre1 Number;
    nbre2 Number;
    BEGIN
    -- Toute reference dans la table SIG_RECO05 doit etre dans la table SIG_RECO04 et vice-versa
    SELECT ACO005_NUMFEU8 into nbre1 FROM SIG_RECO05 minus SELECT RECO04_NUMFEU8 FROM SIG_RECO04;
    SELECT RECO04_NUMFEU8 into nbre2 FROM SIG_RECO04 minus SELECT ACO005_NUMFEU8 FROM SIG_RECO05;
     
     IF (nbre1+nbre2=0) THEN
      EXECUTE IMMEDIATE 'UPDATE CPT_PURGE SET INDCOHAV=0 WHERE NOMTABLE='SIG_RECO05'';
      ELSE
      EXECUTE IMMEDIATE 'UPDATE CPT_PURGE SET INDCOHAV=1 WHERE NOMTABLE='SIG_RECO05'';
     END IF;
    END;
    /
     
    COMMIT;
     
    QUIT

    Cela me retourne l'erreur suivante:

    fich.log" 30 lines, 1299 characters
    --------------------------------------------------------
    103609-Execution du fichier /ficsql/fich.sql via SQLPLUS

    EXECUTE IMMEDIATE 'UPDATE CPT_PURGE SET INDCOHAV=0 WHERE NOMTABLE='SIG_RECO05'';
    *
    ERROR at line 9:
    ORA-06550: line 9, column 70:
    PLS-00103: Encountered the symbol "SIG_RECO05" when expecting one of the following:
    * & = - + ; < / > at in is mod remainder not rem return
    returning <an exponent (**)> <> or != or ~= >= <= <> and or
    like LIKE2_ LIKE4_ LIKEC_ between into using || multiset bulk
    member SUBMULTISET_
    The symbol "* was inserted before "SIG_RECO05" to continue.
    ORA-06550: line 11, column 70:
    PLS-00103: Encountered the symbol "SIG_RECO05" when expecting one of the
    following:
    * & = - + ; < / > at in is mod remainder not rem return
    returning <an exponent (**)> <> or != or ~= >= <= <> and or
    like LIKE2_ LIKE4_ LIKE


    103609-Code retour SQLPLUS 61
    103609-Traitement du fichier /ficsql/fich.sql realise avec erreur

    103609-fin d'execution du fichier /ficsql/fich.sql
    Si certains pouvaient m'aiguiller sur ce point, je les remercie par avance.

    Bonne journée.

    Olivier

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Il faut doubler les apostrophes lorsqu'on construit une chaîne de caractère entre apostrophe justement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    EXECUTE IMMEDIATE 'UPDATE CPT_PURGE SET INDCOHAV=0 WHERE NOMTABLE=''SIG_RECO05''';

  3. #3
    Membre chevronné Avatar de Garuda
    Homme Profil pro
    Chef de projet / Urbaniste SI
    Inscrit en
    Juin 2007
    Messages
    1 285
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Chef de projet / Urbaniste SI
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 285
    Points : 2 071
    Points
    2 071
    Par défaut
    Il faut doubler les quotes !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    EXECUTE IMMEDIATE 'UPDATE CPT_PURGE SET INDCOHAV=0 WHERE NOMTABLE=''SIG_RECO05''';
    PS : Si tu connais le nom de ta table, inutile de faire du sql dynamique !

  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
    Forcément, un select into variable ne doit renvoyer qu'une seule ligne
    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
    -- Controles INTRA SIG
    -- SIG_RECO05
    -- Mise a jour de l'indice de coherence avant purge
    DECLARE
      nbre1 Number := 0;
      nbre2 Number := 0;
    BEGIN
    	-- Toute reference dans la table SIG_RECO05 doit etre dans la table SIG_RECO04 et vice-versa
    	SELECT COUNT(*) INTO nbr1	
      FROM (SELECT ACO005_NUMFEU8 FROM SIG_RECO05 MINUS SELECT RECO04_NUMFEU8 FROM SIG_RECO04);
      -- Peut être éviter de faire le 2ème sélect
      IF nbr1 = 0
      THEN 
        SELECT COUNT(*) INTO nbr2
        FROM (SELECT RECO04_NUMFEU8 INTO nbre2 FROM SIG_RECO04 MINUS SELECT ACO005_NUMFEU8 FROM SIG_RECO05);
    	END IF;
     
    	IF nbre1+nbre2 = 0 THEN
      	EXECUTE IMMEDIATE 'UPDATE CPT_PURGE SET INDCOHAV=0 WHERE NOMTABLE='SIG_RECO05'';
      ELSE
      	EXECUTE IMMEDIATE 'UPDATE CPT_PURGE SET INDCOHAV=1 WHERE NOMTABLE='SIG_RECO05'';
     END IF;
    END;
    Pourquoi un execute immediate à la fin ?

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 31
    Points : 19
    Points
    19
    Par défaut
    Merci pour vos réponses.

    Je regarde et teste les différentes remarques.

    Cdlt,
    Olivier

  6. #6
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    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
     
    declare
      l_nomtab  CPT_PURGE.NOMTABLE%TYPE := 'SIG_RECO05';
    Begin  
      UPDATE CPT_PURGE 
         SET INDCOHAV =  (Select Count(*)
                            From dual
                           Where Exists (Select Null
                                           FROM SIG_RECO04 a
                                                FULL OUTER JOIN
                                                SIG_RECO05 b
                                             On a.RECO04_NUMFEU8 = c.ACO005_NUMFEU8
                                          Where a.rowid Is Null
                                             Or b.rowid Is null         
                                         )       
       WHERE NOMTABLE= l_nomtab;
    End;   
    /
    Et ça a l'avantage de ne pas imposer le traitement mono-utilisateur que les autres solutions implique.

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 31
    Points : 19
    Points
    19
    Par défaut
    Effectivement, il fallait doubler les apostrophes pour que le libellé de la table soit reconnu.

    De même, comme le nom de ta table est connu, j'ai essayé en enlevant le "execute immediate" et ça fonctionne tout aussi bien.

    Merci à Waldar, Garuda et McM pour toutes ces bonnes remarques qui m'ont permis de débloquer la situation.

    Pour l'idée de mnitu, je vais regarder ce que ça donne, mais la solution précédente me sied déjà très bien.

    Bonne journée.

    Cdlt,
    Olivier

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 31
    Points : 19
    Points
    19
    Par défaut
    A mnitu:

    Merci pour l'idée de la jointure externe, ça répond bien à ce que j'ai à faire.

    Par contre, serait-il possible d'avoir quelques précisions:

    - que signifie le %TYPE dans la déclaration de variable ?
    - comment comprendre la notion de table DUAL ?

    Pour le reste, voici ce que j'ai compris et corrigez-moi le cas échéant:

    - par rapport au LEFT/RIGHT OUTER JOIN qui regarde les éléments manquants de l'une ou l'autre des tables impactées, le FULL OUTER JOIN prend en compte les occurrences manquantes des deux tables à la fois,
    - le rowid est l'occurrence au niveau structure de la table et si celui-ci est nul, alors cela signifie, après la jointure effectuée, qu'il existe des occurrences manquantes dans une table par rapport à l'autre,
    - et enfin d'après la requête, cela signifie que le résultat (INDCOHAV) pourra prendre comme valeur 0 (cad qu'il y a exactement les mêmes valeurs dans les deux tables), mais également 1, 2, 3,... selon le nombre d'occurrences (rowid) remontées par la requête.

    Merci d'avance pour les réponses et les éclaircissements à ma compréhension.

    Bonne soirée.

    Cdlt,
    Olivier

  9. #9
    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
    %type : prend la définition de ta colonne en base. Comme ça si ça change (genre un varchar2(50) qui passe en varchar2(100)), tu n'as pas besoin de modifier toutes tes procédures, scripts, etc.. Pratique pour la maintenance, mais moins lisible.

    DUAL : Table systeme qui ne contient qu'une seule ligne, une seule colonne.
    Mnitu l'utilise pour avoir soit 0 soit 1

    Ca devrait (sauf erreur de code) être équivalent à :
    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
    DECLARE
    l_nomtab  VARCHAR2(30) := 'SIG_RECO05';
    BEGIN  
    UPDATE CPT_PURGE 
    SET INDCOHAV =  
    		 (SELECT COUNT(*)
          FROM  (SELECT 1
                  FROM SIG_RECO04 a
                  FULL OUTER JOIN SIG_RECO05 b
                      ON a.RECO04_NUMFEU8 = b.ACO005_NUMFEU8
                  WHERE ROWNUM = 1 
                  AND (a.RECO04_NUMFEU8 IS NULL OR b.ACO005_NUMFEU8 IS NULL)         
                  ) 
          )
    WHERE NOMTABLE= l_nomtab;
    END;

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 31
    Points : 19
    Points
    19
    Par défaut
    Merci McM pour tes réponses.

    Bonne journée.

    Cdlt,
    Olivier

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

Discussions similaires

  1. Utiliser SQL pour archiver des données de tables
    Par com-ace dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 20/08/2006, 18h53
  2. [Système] Problème pour effectuer des calculs
    Par tissard dans le forum Langage
    Réponses: 10
    Dernier message: 09/12/2005, 14h07
  3. [MySQL] Erreur sql pour inserer des checkbox
    Par digger dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 25/11/2005, 11h06
  4. Pb pour cacher des contrôles à l'ouverture d'une page
    Par Anne1969 dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 10/01/2005, 15h16
  5. configurer sql pour envoyer des mails
    Par arwen dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 29/07/2003, 15h28

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