2010-06-09 3 views
0

bons gourous de jour,ORA-06502: PL/SQL: erreur numérique ou de la valeur: tampon de chaîne de caractères trop petite avec fonctions d'agrégation Oracle

J'ai un script qui renseigne les tables sur une base régulière qui se est écrasé et a donné ci-dessus Erreur. Ce qui est étrange, c'est que cela a fonctionné pendant près de 3 mois sur le système de production sans problème et s'est brusquement écrasé la semaine dernière. Il n'y a pas eu de changements sur les tables autant que je sache.

Est-ce que quelqu'un a déjà rencontré quelque chose comme ça? Je crois que cela a quelque chose à voir avec les fonctions agrégées que j'implémente dans ce domaine; mais cela a fonctionné initialement.

veuillez; Veuillez trouver ci-joint la partie du script que j'ai développé dans une procédure qui, je pense, donne l'erreur.

CREATE OR REPLACE PROCEDURE V1 EST

--DECLARE

v_a  VARCHAR2(4000); 
    v_b  VARCHAR2(4000); 
    v_c  VARCHAR2(4000); 
    v_d  VARCHAR2(4000); 
    v_e  VARCHAR2(4000); 
    v_f  VARCHAR2(4000); 
    v_g  VARCHAR2(4000); 
    v_h  VARCHAR2(4000); 
    v_i  VARCHAR2(4000); 
    v_j  VARCHAR2(4000); 
    v_k  VARCHAR2(4000); 
    v_l  VARCHAR2(4000); 
    v_m  VARCHAR2(4000); 
    v_n  NUMBER(10); 
    v_o  VARCHAR2(4000); 

-
- Procédure qui renseigne table DEMO

 BEGIN 

       -- Delete all from the DEMO table 
       DELETE FROM DEMO; 

       -- Populate fields in DEMO from DEMOV1 
       INSERT INTO DEMO(ID, D_ID, CTR_ID, C_ID, DT_NAM, TP, BYR, ENY, 
           ONG, SUMM, DTW, REV, LD, MD, STAT, CRD) 
       SELECT ID, D_ID, CTR_ID, C_ID, DT_NAM, TP, TO_NUMBER(TO_CHAR(BYR,'YYYY')), 
        TO_NUMBER(TO_CHAR(NVL(ENY,SYSDATE),'YYYY')), CASE WHEN ENY IS NULL THEN 'Y' ELSE 'N' END, SUMMARY, DTW, 
        REV, LD, MD, '1', SYSDATE 
       FROM DEMOV1; 

      -- LOOP THROUGH DEMO TABLE 
      FOR j IN (SELECT ID, CTR_ID, C_ID FROM DEMO) 
      LOOP 




       Select semic_concat(TXTDESC) 
       INTO v_a 
       From GEOT 
       WHERE ID = j.ID; 



       SELECT COUNT(*) 
       INTO v_n 
       FROM MERP M, PROJ P 
       WHERE M.MID = P.COD 
       AND ID = j.ID 
       AND PROAC IS NULL; 

       IF (v_n > 0) 
       THEN 


        Select semic_concat(PRO) 
        INTO v_b 
        FROM MERP M, PROJ P 
        WHERE M.MID = P.COD 
        AND ID = j.ID; 

       ELSE 


        Select semic_concat(PRO || '(' || PROAC || ')') 
        INTO v_b 
        FROM MERP M, PROJ P 
        WHERE M.MID = P.COD 
        AND ID = j.ID; 

       END IF; 


       Select semic_concat(VOCNAME('P02',COD)) 
       INTO v_c 
       From PAR 
       WHERE ID = j.ID; 



       Select semic_concat(VOCNAME('L05',COD)) 
       INTO v_d 
       From INST 
       WHERE ID = j.ID; 


       Select semic_concat(NVL(AUTHOR,'Anon') ||' ('||to_char(PUB,'YYYY')||') '||TITLE||', '||EDT) 
       INTO v_e 
       From REFE 
       WHERE ID = j.ID; 



       Select semic_concat(NAM) 
       INTO v_f 
       FROM EDM E, EDO EO 
       WHERE E.EDMID = EO.EDOID 
       AND ID = j.ID; 



       Select semic_concat(VOCNAME('L08', COD)) 
       INTO v_g 
       FROM AVA 
       WHERE ID = j.ID; 



       SELECT or_concat(NAM) 
       INTO v_o 
       FROM CON 
       WHERE ID = j.ID 
       AND NAM = 'Unknown'; 

        IF (v_o = 'Unknown') 
        THEN 

         Select or_concat(JOBTITLE || ' (' || EMAIL || ')') 
         INTO v_h 
         FROM CON 
         WHERE ID = j.ID; 

        ELSE 

         Select or_concat(NAM || ' (' || EMAIL || ')') 
         INTO v_h 
         FROM CON 
         WHERE ID = j.ID; 

        END IF; 



       Select commaencap_concat(COD) 
       INTO v_i 
       FROM PAR 
       WHERE ID = j.ID; 

       IF (v_i = ',') 
       THEN 

        v_i := null; 

       ELSE 

        Select commaencap_concat(COD) 
        INTO v_i 
        FROM PAR 
        WHERE ID = j.ID; 


       END IF; 



       Select commaencap_concat(COD) 
       INTO v_j 
       FROM INST 
       WHERE ID = j.ID; 

       IF (v_j = ',') 
       THEN 

        v_j := null; 

       ELSE 

        Select commaencap_concat(COD) 
        INTO v_j 
        FROM INST 
        WHERE ID = j.ID; 

       END IF; 



       Select commaencap_concat(COD) 
        INTO v_k 
        FROM SAR 
        WHERE ID = j.ID; 

       IF (v_k = ',') 
       THEN 

        v_k := null; 

       ELSE 

        Select commaencap_concat(COD) 
        INTO v_k 
        FROM SAR 
        WHERE ID = j.ID; 

       END IF; 




       Select commaencap_concat(CONID) 
        INTO v_l 
        FROM CON 
        WHERE ID = j.ID; 

       IF (v_l = ',') 
       THEN 

        v_l := null; 

       ELSE 

        Select commaencap_concat(CONID) 
        INTO v_l 
        FROM CON 
        WHERE ID = j.ID; 

       END IF; 



       Select commaencap_concat(PROID) 
        INTO v_m 
        FROM PRO 
        WHERE ID = j.ID; 

       IF (v_m = ',') 
       THEN 

        v_m := null; 

       ELSE 

        Select commaencap_concat(PROID) 
        INTO v_m 
        FROM PRO 
        WHERE ID = j.ID; 

       END IF; 

       -- UPDATE DEMO TABLE 
       UPDATE DEMO 
       SET GEOC = v_a, 
        PRO = v_b, 
        PAR = v_c, 
        INS = v_d, 
        REFER = v_e, 
        ORGR = v_f, 
        AVAY = v_g, 
        CON = v_h, 
        DTH = v_i, 
        INST = v_j, 
        SA = v_k, 
        CC = v_l, 
        EDPR = v_m, 
        CTR = (SELECT NAM 
            FROM EDM 
            WHERE EDMID = j.CTR_ID), 
        COLL = (SELECT NAM 
            FROM EDM 
            WHERE EDMID = j.C_ID) 

       WHERE ID = j.ID; 

      END LOOP; 


     END V1; 

/

L'agrégat fonctions, c ommaencap_concat (encapsule avec une virgule), or_concat (concats avec un ou) et semic_concat (enchaînements avec un point-virgule).

Les tables restantes utilisées sont toutes liées à la table principale DEMO.

J'ai vérifié la taille des colonnes et il ne semble pas y avoir de problème. J'ai essayé d'exécuter les instructions SELECT seules et elles donnent la même erreur sans peupler les tables.

Des indices?

Un grand merci pour votre soutien anticipé.

Merci APC pour votre aide; en particulier le conseil rowtype et debug. J'ai vérifié toutes les colonnes les unes par rapport aux autres et ai fait celles qui étaient de moins de 4000 octets à 4000 octets mais je reçois toujours le même message d'erreur.

L'instruction SELECT j'ai essayé était avec l'une des fonctions d'agrégation qui est dans la procédure:

  Select semic_concat(TXTDESC) 
      -- INTO v_a 
      From GEOT 
      WHERE ID IN (SELECT ID FROM DEMO); 

et il a soulevé la même erreur de tampon de chaîne trop petite; mais quand j'ai ajouté un groupe à la déclaration cela a fonctionné.

  Select semic_concat(TXTDESC) 
      -- INTO v_a 
      From GEOT 
      WHERE ID IN (SELECT ID FROM DEMO) 
      GROUP BY ID; 

J'ai essayé d'échanger toutes les occurrences de telles instructions dans la procédure, mais cela donne toujours la même erreur. Encore merci; Travaille toujours dessus.

+3

Il serait extrêmement utile si vous deviez nous donner un indice, tel qu'un exemple de code. Aussi la version de la base de données. Et peut-être un peu de contexte (ce que fait votre application). – APC

+0

APC a raison. Sans un échantillon de code, nous ne pouvons pas faire d'inspection de code pour vous aider, Tunde. Bien sûr, vous êtes moralement obligé de crypter tous les noms de variables significatives, afin d'éviter que nous devinions que vous travailliez ou que vous vous intéressiez, pour des raisons évidentes de confidentialité et pour respecter les politiques de sécurité de votre entreprise. – UltraCommit

+0

@APC, merci. @Le poulet dans la cuisine, j'ai crypté autant que possible. La chose étrange est que les instructions SQL seules ont cessé de fonctionner avec les fonctions d'agrégat lorsqu'elles sont isolées de la procédure. Merci. – Tunde

Répondre

5

Fonctions d'agrégation, er, agrégat. Cela signifie qu'ils ajoutent des nombres ou concaténent des chaînes ensemble. Plus la valeur de la source est grande, plus le produit aggegated est grand.

Sans plus de détails, il est difficile d'en être certain, mais l'explication la plus probable est que quelque chose dans votre data a changé, avec pour conséquence que votre valeur agrégée est trop grande pour tenir dans la colonne cible.

modifier

" I tried the SELECT statement on its own and gives the same error... "

Hmmm, qui SELECT? Votre procédure a des tas d'entre eux.

Quoi qu'il en soit, la chose que vous devez faire est d'apprendre à déboguer votre code. Le meilleur moyen de déboguer PL/SQL est avec un IDE qui supporte de tels efforts. TOAD et PL/SQL Developer le font tous deux, tout comme le propre développeur SQL d'Oracle. Find out more.

Vous pouvez également utiliser DBMS_OUTPUT (AKA le Débogueur du Diable) et interpoler de nombreux appels DBMS_OUTPUT.PUT_LINE() pour voir quelle instruction vous allez exécuter et la longueur des valeurs pertinentes.

Toutefois, étant donné que toutes vos variables de chaîne PL/SQL sont la longueur de colonne SQL maximale - varchar2(4000) - je me concentrerais sur le code qui remplit votre variable v_n. number(10) n'est en aucun cas le plus grand nombre possible de SQL, de sorte que vous êtes en train d'enfreindre une limite de mémoire qui semble le plus probable. Bien que, puisque le message d'erreur mentionne chaîne tampon, je peux vous vendre un bum steer.

L'autre possibilité est cette instruction UPDATE finale. Toutes les colonnes de DEMO sont-elles classées varchar2(4000)? Si non, alors vous devez les regarder. Il est bon de spécifier les variables en utilisant la% syntaxe TYPE:

v_a demo.geoc%TYPE; 
v_b demo.pro%TYPE; 

Ou, pour diminuer la frappe, spécifiez une seule variable d'enregistrement:

v_demo demo%rowtype; 

qui vous pouvez faire référence comme ceci:

select semic_concat(TXTDESC) 
into v_demo.geoc 
From GEOT 
WHERE ID = j.ID; 

(Incidemment, il est possible d'utiliser une variable de niveau ligne dans les instructions de mise à jour en utilisant la syntaxe UPDATE ... SET ROW =, mais je ne pense pas que ce serait approprié dans votre situation.)

modifier 2

Encore une fois, NO_DATA_FOUND des points à un problème de données. À moins que notre base de données soit en lecture seule, nous devons nous attendre à ce que les données changent et nous devrions gérer les exceptions liées aux données. Si la raison pour laquelle vous ne gérez pas NO_DATA_FOUND est parce que les données doivent toujours être là, vous avez un problème plus large, éventuellement une clé étrangère manquante ou désactivée. Généralement, il est plus sûr de supposer que nous obtiendrons NO_DATA_FOUND, TOO_MANY_ROWS, etc et d'inclure des gestionnaires d'exception utiles pour consigner les détails pertinents.


note (1) Ou apprendre à développer Premier test à l'aide d'un harnais de test unitaire, mais cela est une porte de l'écurie, le cheval scénario disparu ...

+0

oui. J'ai essayé l'instruction SELECT seule et donne la même erreur ... – Tunde

+0

Voté pour le terme "Débogueur du diable" –

+0

APC, merci beaucoup pour votre aide et votre aide. Je reçois maintenant un message d'erreur différent de "NO DATA FOUND" avec l'une des instructions select impliquant les fonctions d'agrégat. La chose étrange est que cela a fonctionné pendant près de 3 mois ... travaillant toujours là-dessus. Merci encore une fois; J'apprécie vraiment vos efforts. – Tunde

Questions connexes