0

各位大师们好

我有一个脚本定期填充表,该脚本崩溃并出现上述错误。奇怪的是,它在生产系统上运行了近3个月没有任何问题,上周突然崩溃。据我所知,桌子上没有任何变化。

有没有人遇到过这样的事情?我相信这与我在其中实现的聚合函数有关;但它最初有效。

请; 请找到附加的脚本部分,我已经开发成一个我认为会出错的程序。

创建或替换过程 V1 是

- 宣布

    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(用 or 连接)和 semic_concat(用分号连接)。

其余使用的表都链接到主表DEMO。

我检查了列大小,似乎没有问题。我尝试单独执行 SELECT 语句,但它们在不填充表的情况下给出了相同的错误。

有什么线索吗?

非常感谢您的预期支持。

感谢 APC 的所有帮助;特别是行类型和调试建议。我已经检查了所有列,并将那些小于 4000 字节的列设置为 4000 字节,但我仍然收到相同的错误消息。

我尝试的 SELECT 语句使用过程中的聚合函数之一:

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

并且它引发了相同的字符串缓冲区太小错误;但是当我在语句中添加一个 group by 时,它起作用了。

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

我尝试在过程中交换所有出现的此类语句,但它仍然给出相同的错误。再次感谢; 仍在努力。

4

1 回答 1

5

聚合函数,呃,聚合。这意味着它们将数字相加或将字符串连接在一起。源值越大,聚合产品越大。

在不了解更多细节的情况下很难确定,但最可能的解释是您的数据中的某些内容发生了变化,结果是您的聚合值现在太大而无法放入目标列。

编辑

“我自己尝试了 SELECT 语句并给出了同样的错误......”

嗯,哪个SELECT?你的程序有很多。

无论如何,你需要做的就是学会调试你的代码(1)

调试 PL/SQL 的最佳方式是使用支持此类工作的 IDE。TOAD 和 PL/SQL Developer 都这样做,Oracle 自己的(免费)产品 SQL Developer 也是如此。 了解更多

或者,您可以使用 DBMS_OUTPUT(又名魔鬼调试器)并插入大量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 =语法在更新语句中使用行级变量,但我认为这不适合您的情况。)

编辑 2

再次NO_DATA_FOUND指出数据问题。除非我们的数据库是只读的,否则我们必须预期数据会发生变化,并且我们应该处理与数据相关的异常。如果您不处理的原因NO_DATA_FOUND是因为数据应该始终存在,那么您有一个更广泛的问题,可能是缺少或禁用的外键。一般来说,假设我们将获得NO_DATA_FOUND,TOO_MANY_ROWS等并包含有用的异常处理程序来记录相关细节会更安全。


脚注(1) 或者学习使用单元测试工具来开发它Test First,但这是一个稳定的门,马走了场景......

于 2010-06-09T11:21:45.980 回答