【发布时间】:2021-08-28 10:06:29
【问题描述】:
我们有一个接收 200 条自定义类型记录的过程。 使用 For 循环将这些记录插入到表 XYZ 中。
(不幸的是,这个 XYZ 表没有任何主键,它有大约 650 万条记录)。 现在,一旦插入完成,就会执行删除操作。
现有代码:-
PROCEDURE XXX_FIN_INSERT_DATA_PRC_YYY_AP (p_in_YYY_AP XXX_FIN_YYY_AP_TYPE_V2) IS
test_gl_t XXX_FIN_YYY_AP_TYPE_V2;
BEGIN
test_gl_t := p_in_YYY_AP;
FOR i IN test_gl_t.FIRST .. test_gl_t.LAST
LOOP
INSERT
INTO XXX_FIN_YYY_AP_TBL(
DOC_TYPE
,VENDOR_NAME
,SUPPLIER_SEGMENT1
,INVOICE_NUMBER
,INVOICE_DATE
,INVOICE_AMOUNT
,COST_CENTER
,PO_HEADER_SEGMENT1
,CHECK_NUMBER
,CHECK_DATE
,CHECK_AMOUNT
,INVOICE_ID
,CHECK_ID
,DIST_AMOUNT
,FILE_ID
,XXX_RECORD_ID )
VALUES
(
test_gl_t (i).DOC_TYPE
,test_gl_t (i).VENDOR_NAME
,test_gl_t (i).SUPPLIER_SEGMENT1
,test_gl_t (i).INVOICE_NUMBER
,test_gl_t (i).INVOICE_DATE
,test_gl_t (i).INVOICE_AMOUNT
,test_gl_t (i).COST_CENTER
,test_gl_t (i).PO_HEADER_SEGMENT1
,test_gl_t (i).CHECK_NUMBER
,test_gl_t (i).CHECK_DATE
,test_gl_t (i).CHECK_AMOUNT
,test_gl_t (i).INVOICE_ID
,test_gl_t (i).CHECK_ID
,test_gl_t (i).DIST_AMOUNT
,test_gl_t (i).FILE_ID
,XXX_FIN_JOURNALS_REC_SEQ.NEXTVAL);
DELETE FROM XXX_FIN_YYY_AP_TBL WHERE
DOC_TYPE = test_gl_t (i).DOC_TYPE
AND VENDOR_NAME = test_gl_t (i).VENDOR_NAME
AND SUPPLIER_SEGMENT1 = test_gl_t (i).SUPPLIER_SEGMENT1
AND INVOICE_NUMBER = test_gl_t (i).INVOICE_NUMBER
AND INVOICE_DATE = test_gl_t (i).INVOICE_DATE
AND COST_CENTER = test_gl_t (i).COST_CENTER
AND CHECK_NUMBER = test_gl_t (i).CHECK_NUMBER
AND CHECK_DATE = test_gl_t (i).CHECK_DATE
AND INVOICE_ID = test_gl_t (i).INVOICE_ID
AND CHECK_ID = test_gl_t (i).CHECK_ID
AND FILE_ID < test_gl_t (i).FILE_ID;
END LOOP;
END XXX_FIN_INSERT_DATA_PRC_YYY_AP;
我尝试将其修改为:-
PROCEDURE XXX_FIN_INSERT_DATA_PRC_YYY_AP_NEW (p_in_YYY_AP XXX_FIN_YYY_AP_TYPE_V2)
IS
test_gl_t XXX_FIN_YYY_AP_TYPE_V2;
TYPE temp_table_type is TABLE of XXX_FIN_YYY_AP_TBL%ROWTYPE INDEX BY PLS_INTEGER;
temp_table temp_table_type;
CURSOR c is SELECT * FROM XXX_FIN_YYY_AP_TBL ORDER BY INVOICE_ID DESC;
BEGIN
test_gl_t := p_in_YYY_AP;
OPEN c;
FETCH c BULK COLLECT INTO temp_table LIMIT 5000;
LOOP
FOR idx IN 1..temp_table.LAST LOOP
FOR i IN test_gl_t.FIRST .. test_gl_t.LAST LOOP
IF ( temp_table(idx).DOC_TYPE = test_gl_t(i).DOC_TYPE
AND temp_table(idx).VENDOR_NAME = test_gl_t(i).VENDOR_NAME
AND temp_table(idx).SUPPLIER_SEGMENT1 = test_gl_t(i).SUPPLIER_SEGMENT1
AND temp_table(idx).INVOICE_NUMBER = test_gl_t(i).INVOICE_NUMBER
AND temp_table(idx).INVOICE_DATE = test_gl_t(i).INVOICE_DATE
AND temp_table(idx).COST_CENTER = test_gl_t(i).COST_CENTER
AND temp_table(idx).CHECK_NUMBER = test_gl_t(i).CHECK_NUMBER
AND temp_table(idx).CHECK_DATE = test_gl_t(i).CHECK_DATE
AND temp_table(idx).INVOICE_ID = test_gl_t(i).INVOICE_ID
AND temp_table(idx).CHECK_ID = test_gl_t(i).CHECK_ID
AND temp_table(idx).FILE_ID < test_gl_t(i).FILE_ID) THEN
INSERT INTO XXX_FIN_YYY_AP_TBL (
DOC_TYPE,VENDOR_NAME,SUPPLIER_SEGMENT1,INVOICE_NUMBER,INVOICE_DATE,INVOICE_AMOUNT
,COST_CENTER,PO_HEADER_SEGMENT1,CHECK_NUMBER,CHECK_DATE,CHECK_AMOUNT,INVOICE_ID
,CHECK_ID,DIST_AMOUNT,FILE_ID,XXX_RECORD_ID
)
VALUES
(
test_gl_t(i).DOC_TYPE
,test_gl_t(i).VENDOR_NAME
,test_gl_t(i).SUPPLIER_SEGMENT1
,test_gl_t(i).INVOICE_NUMBER
,test_gl_t(i).INVOICE_DATE
,test_gl_t(i).INVOICE_AMOUNT
,test_gl_t(i).COST_CENTER
,test_gl_t(i).PO_HEADER_SEGMENT1
,test_gl_t(i).CHECK_NUMBER
,test_gl_t(i).CHECK_DATE
,test_gl_t(i).CHECK_AMOUNT
,test_gl_t(i).INVOICE_ID
,test_gl_t(i).CHECK_ID
,test_gl_t(i).DIST_AMOUNT
,test_gl_t(i).FILE_ID
,XXX_FIN_JOURNALS_REC_SEQ.NEXTVAL
);
END IF;
END LOOP;
END LOOP;
EXIT WHEN c%notfound;
END LOOP;
CLOSE c;
END XXX_FIN_INSERT_DATA_PRC_YYY_AP_NEW;
我运行了调用我的过程的主服务。 服务挂了。 现在当我在我的代码中添加调试语句并尝试编译 SQL Developer 时挂起。 我重新启动了很多次,但我无法恢复。
我请求 DBA 对此提供帮助。
现在我向专家提出的问题是:-
- 我写的代码有什么问题?有更好的方法吗?
- 我也为该表编制了索引,但我想知道是否有 更好的解决方案。
任何建议/讨论/提示都会有所帮助。
问候, 德布
【问题讨论】:
标签: sql oracle query-optimization bulkinsert