在游标循环中串联varchar2数据类型时遇到问题。
过程在循环中迭代以构建in子句以批量执行插入和删除操作。该过程将针对每1000个帐号批量运行。
对于少量记录,它可以工作,但是当尝试在循环中连接大量记录(临时表中的36451477)时,它会抛出。
java.sql.SQLException:ORA-06502:PL / SQL:数字或值错误: 字符串缓冲区太小ORA-06512:在 “ QA01BT.LOAD_ITEM_DATA_TO_CONSOLIDATE”,第23行ORA-06512:在第1行
我已将搜索ID的最大值限制为32767,但仍然无法正常工作。
还有其他方法可以实现吗?
create or replace PROCEDURE LOAD_ITEM_DATA_TO_CONSOLIDATE(updatecount OUT NUMBER
)
IS
cnt NUMBER := 0;
c_limit CONSTANT PLS_INTEGER DEFAULT 1000;
search_id varchar2(32727);
TYPE account_array
IS TABLE OF VARCHAR2(255) INDEX BY BINARY_INTEGER;
l_data ACCOUNT_ARRAY;
CURSOR account_cursor IS
SELECT DISTINCT account_no AS account_num
FROM item_temp;
BEGIN
OPEN account_cursor;
LOOP
FETCH account_cursor bulk collect INTO l_data limit c_limit;
search_id := '''';
FOR i IN 1 .. l_data.count LOOP
IF( i != 1 ) THEN
search_id := search_id
|| ','
|| ''''
|| l_data(i)
|| '''';
ELSE
search_id := search_id
|| l_data(i)
|| '''';
END IF;
END LOOP;
BEGIN
SAVEPOINT move_data_to_temp_table;
EXECUTE IMMEDIATE 'delete from item where ACCOUNT_NO IN('||search_id||')';
EXECUTE IMMEDIATE 'insert into item(ID,ACCOUNT_NO,ITEM_ID,ITEM_VALUE) select HIBERNATE_SEQUENCE.nextval,temp.ACCOUNT_NO,temp.ITEM_ID,temp.ITEM_VALUE from item_TEMP temp where ACCOUNT_NO IN('||search_id||')';
cnt := cnt + SQL%rowcount;
COMMIT;
EXCEPTION WHEN OTHERS THEN ROLLBACK to move_data_to_temp_table;
END;
EXIT WHEN account_cursor%NOTFOUND;
END LOOP;
updatecount := cnt;
CLOSE account_cursor;
END LOAD_ITEM_DATA_TO_CONSOLIDATE;
答案 0 :(得分:0)
这似乎有些过分设计。为什么不只是这个?
create or replace PROCEDURE LOAD_ITEM_DATA_TO_CONSOLIDATE
(updatecount OUT NUMBER)
IS
BEGIN
delete from item
where ACCOUNT_NO IN ( SELECT account_no
FROM item_temp);
insert into item(ID,ACCOUNT_NO,ITEM_ID,ITEM_VALUE)
select HIBERNATE_SEQUENCE.nextval, temp.ACCOUNT_NO, temp.ITEM_ID, temp.ITEM_VALUE
from item_TEMP temp ;
updatecount := SQL%rowcount;
END LOAD_ITEM_DATA_TO_CONSOLIDATE;
答案 1 :(得分:0)
如果您确定需要分批执行此操作,并且担心该字符串太长或列表中的元素过多(最大为1000),则应尝试将值放入数组,然后使用IN通过表函数或对表的直接引用对数组进行操作。
额外好处:无需动态SQL!
类似这样的东西:
CREATE OR REPLACE TYPE strings_t IS TABLE OF VARCHAR2 (255)
/
CREATE OR REPLACE PROCEDURE load_item_data_to_consolidate (
updatecount OUT NUMBER)
IS
cnt NUMBER := 0;
c_limit CONSTANT PLS_INTEGER DEFAULT 1000;
l_data strings_t;
CURSOR account_cursor
IS
SELECT DISTINCT account_no AS account_num FROM item_temp;
BEGIN
OPEN account_cursor;
LOOP
FETCH account_cursor BULK COLLECT INTO l_data LIMIT c_limit;
BEGIN
SAVEPOINT move_data_to_temp_table;
DELETE FROM item
WHERE account_no IN (SELECT COLUMN_VALUE FROM TABLE (l_data));
INSERT INTO item (id,
account_no,
item_id,
item_value)
SELECT hibernate_sequence.NEXTVAL,
temp.account_no,
temp.item_id,
temp.item_value
FROM item_temp temp
WHERE account_no IN (SELECT COLUMN_VALUE FROM TABLE (l_data));
cnt := cnt + SQL%ROWCOUNT;
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK TO move_data_to_temp_table;
END;
EXIT WHEN account_cursor%NOTFOUND;
END LOOP;
END;