ORA-06502: PL / SQL: ошибка с числовым значением или значением: буфер строки символов слишком мал с агрегатными функциями Oracle - PullRequest
0 голосов
/ 09 июня 2010

Добрый день, гуру,

У меня есть скрипт, который регулярно заполняет таблицы, который вылетал и выдавал вышеуказанную ошибку.Странно то, что он работал в рабочей системе почти 3 месяца без проблем и внезапно потерпел крах на прошлой неделе.Насколько я знаю, в таблицах не было никаких изменений.

Кто-нибудь сталкивался с чем-то подобным раньше?Я считаю, что это как-то связано с агрегатными функциями, которые я реализую в нем;но сработало изначально.

пожалуйста;пожалуйста, приложите часть сценария, которую я разработал, к процедуре, которую, я считаю, выдает ошибку.

СОЗДАНИЕ ИЛИ ЗАМЕНА ПРОЦЕДУРЫ V1 IS

- ОБЪЯВИТЬ

    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);

-
- Процедура, которая заполняет таблицу 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;

/

Агрегатные функции, commaencap_concat (инкапсулирует запятой), or_concat (конкатас с или) иsemic_concat (concats с точкой с запятой).

все остальные используемые таблицы связаны с основной таблицей DEMO.

Я проверил размеры столбцов, и, похоже, проблем нет.Я попытался выполнить только операторы SELECT, и они выдают ту же ошибку, не заполняя таблицы.

Любые подсказки?

Большое спасибо за вашу ожидаемую поддержку.

Спасибо APC за всетвоя помощь;особенно тип строки и совет отладки.Я проверил все столбцы друг против друга и создал столбцы размером от 4000 до 4000 байтов, но все равно получаю одно и то же сообщение об ошибке.

Оператор SELECT, который я пробовал, был с одним изагрегатные функции, которые есть в процедуре:

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

, и она вызвала ту же ошибку строкового буфера слишком мала;но когда я добавил группу к заявлению, это сработало.

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

Я пытался поменять местами все вхождения таких операторов в процедуре, но все равно выдает ту же ошибку.Еще раз спасибо;все еще работает над этим.

1 Ответ

5 голосов
/ 09 июня 2010

Агрегирующие функции, т.е. агрегат.Это означает, что они добавляют числа или объединяют строки вместе.Чем больше значение источника, тем больше агрегированный продукт.

Не зная больше деталей, трудно быть уверенным, но наиболее вероятное объяснение состоит в том, что что-то в ваших данных изменилось, вследствие чего ваше агрегированное значение теперь слишком велико, чтобы соответствоватьв столбце назначения.

edit

"Я попытался выполнить оператор SELECT самостоятельно и выдает ту же ошибку ..."

Хммм, какой ВЫБРАТЬ?В вашей процедуре есть куча из них.

В любом случае, вам нужно научиться отлаживать ваш код . (1)

Лучший способ отладки PL / SQL - это IDE, которая поддерживает такие попытки.Это делают и TOAD, и PL / SQL Developer, так же как и собственный (бесплатный) продукт Oracle Developer. Узнайте больше .

В качестве альтернативы вы можете использовать DBMS_OUTPUT (AKA the Devil's Debugger) и интерполировать множество вызовов DBMS_OUTPUT.PUT_LINE(), чтобы увидеть, какой оператор вы собираетесь выполнить, и длину соответствующих значений.

Однако, учитывая, что все ваши строковые переменные PL / SQL имеют максимальную длину столбца SQL - varchar2(4000) - я бы сосредоточился на коде, который заполняет вашу переменную v_n.number(10) ни в коем случае не самое большое число, которое можно хранить в SQL, так как вы нарушаете ограничение буфера, которое кажется наиболее вероятным кандидатом.Хотя, поскольку в сообщении об ошибке упоминается строковый буфер, возможно, я продаю вам задницу.

Другая возможность - это последний оператор UPDATE.Все ли столбцы DEMO имеют размер varchar2(4000)?Если нет, то вам нужно посмотреть на них.Рекомендуется указывать переменные с использованием синтаксиса% TYPE:

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

. Или, чтобы сохранить тип ввода, укажите одну переменную записи:

v_demo demo%rowtype;

На которую вы можете ссылаться следующим образом:

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

(Кстати, можно использовать переменную уровня строки в операторах обновления с использованием синтаксиса UPDATE ... SET ROW =, но я не думаю, что это будет уместно в вашей ситуации.)

edit 2

Снова NO_DATA_FOUND указывает на проблему с данными.Если наша база данных не предназначена только для чтения, мы должны ожидать, что данные изменятся, и мы должны обрабатывать исключения, связанные с данными.Если причина, по которой вы не обрабатываете NO_DATA_FOUND, заключается в том, что данные всегда должны быть там, у вас есть более широкая проблема, возможно, отсутствует или отключен внешний ключ.Как правило, безопаснее предположить, что мы получим NO_DATA_FOUND, TOO_MANY_ROWS и т. Д. И включим полезные обработчики исключений для регистрации соответствующих деталей.


сноска (1) Или научитесь разрабатывать его. Тест Сначала используйте модульный тестовый жгут, но это сценарий стабильной двери, лошадь ушла ...

...