Tun*_*nde 0 oracle plsql aggregate-functions
美好的一天大师,
我有一个脚本定期填充表崩溃并给出上述错误.奇怪的是,它已经在生产系统上运行了近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);
Run Code Online (Sandbox Code Playgroud)
-
- 填充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;
Run Code Online (Sandbox Code Playgroud)
/
聚合函数,commaencap_concat(用逗号封装),or_concat(带或的concats)和semic_concat(带分号的concats).
使用的其余表都链接到主表DEMO.
我检查了列大小,似乎没有问题.我尝试单独执行SELECT语句,它们在不填充表的情况下提供相同的错误.
有线索吗?
非常感谢您的期望支持.
感谢APC的所有帮助; 特别是rowtype和debug建议.我已经检查了所有列,并且已经将那些小于4000字节到4000字节的列进行了检查,但我仍然得到相同的错误消息.
我尝试的SELECT语句是使用过程中的一个聚合函数:
Select semic_concat(TXTDESC)
-- INTO v_a
From GEOT
WHERE ID IN (SELECT ID FROM DEMO);
Run Code Online (Sandbox Code Playgroud)
它引发了字符串缓冲区相同的错误太小; 但当我在声明中添加了一个小组时,它起作用了.
Select semic_concat(TXTDESC)
-- INTO v_a
From GEOT
WHERE ID IN (SELECT ID FROM DEMO)
GROUP BY ID;
Run Code Online (Sandbox Code Playgroud)
我尝试在过程中交换所有出现的这样的语句,但它仍然给出了相同的错误.再次感谢; 还在努力.
聚合函数,呃,聚合.这意味着他们添加数字或将字符串连接在一起.源值越大,产品越大.
在不了解更多细节的情况下很难确定,但最可能的解释是数据中的某些内容发生了变化,结果是您的聚合值现在太大而无法放入目标列.
编辑
"我自己尝试了SELECT语句并给出了同样的错误......"
嗯,哪个SELECT?你的程序很多.
无论如何,您需要做的是学习调试代码.(1)
调试PL/SQL的最佳方法是使用支持此类工作的IDE.TOAD和PL/SQL Developer都这样做,Oracle自己的(免费)产品SQL Developer也是如此. 了解更多.
或者,您可以使用DBMS_OUTPUT(AKA Devil的调试器)并插入大量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;
Run Code Online (Sandbox Code Playgroud)
或者,要保存键入,请指定单个记录变量:
v_demo demo%rowtype;
Run Code Online (Sandbox Code Playgroud)
您可以这样引用:
select semic_concat(TXTDESC)
into v_demo.geoc
From GEOT
WHERE ID = j.ID;
Run Code Online (Sandbox Code Playgroud)
(顺便说一句,可以使用UPDATE ... SET ROW =语法在更新语句中使用行级变量,但我认为这不适合您的情况.)
编辑2
再次NO_DATA_FOUND指出数据问题.除非我们的数据库是只读的,否则我们必须预期数据会发生变化,我们应该处理与数据相关的异常.如果你不处理的原因NO_DATA_FOUND是因为数据应该总是在那里你有一个更广泛的问题,可能是丢失或禁用外键.一般是比较安全的假设,我们会得到NO_DATA_FOUND,TOO_MANY_ROWS等,并包括有帮助的异常处理程序来记录相关细节.
脚注(1) 或学会开发测试首先使用单元测试安全带,但这是一个稳定的门,马走了场景......
| 归档时间: |
|
| 查看次数: |
7848 次 |
| 最近记录: |