避免多次插入到oracle表中[关闭]
Posted
技术标签:
【中文标题】避免多次插入到oracle表中[关闭]【英文标题】:Avoid multiple insert into oracle table [closed] 【发布时间】:2017-12-28 22:58:49 【问题描述】:**加载 100,000 行的更快方法。而不是多个插入想要 1 个插入 ** 我有一个从多个 oracle 表中获取数据的脚本。根据订单类型,临时表有多个插入。根据订单类型插入 100,000 条或更多记录。基于订单类型的多个插入需要 12-14 分钟。有更快的方法吗?
prompt Querying freight ...
SET serveroutput ON SIZE 1000000
DECLARE
CURSOR c_progpcon
IS
SELECT cust_id
,div_no
FROM dss.program_processing_controls;
CURSOR c_custord(in_orgrole_id_customer IN dss.orders.orgrole_id_customer%TYPE)
IS
SELECT id order_id
,order_type
,order_number
,customer_po
FROM dss.orders
WHERE order_type = 'CUST'
AND orgrole_id_customer = in_orgrole_id_customer;
CURSOR c_outbound(in_order_id IN dss.orders.id%TYPE)
IS
SELECT ship.id ship_id
,ship.shipper_no
,shptrk.id shptrk_id
,shptrk.waybill
,shptrk.estimated_freight
,shptrk.actual_freight
,shptrk.dt_created
FROM dss.shipments ship
,dss.shipment_trackings shptrk
WHERE ship.order_id = in_order_id
AND shptrk.ship_id = ship.id
-- and ship.id = 2290451
AND shptrk.dt_created BETWEEN TO_DATE('01-JAN-2017','dd-MON-yyyy')
AND TO_DATE('31-DEC-2017','dd-MON-yyyy');
CURSOR c_ordsch(in_order_id IN dss.orders.id%TYPE)
IS
SELECT ordsch.id ordsch_id
FROM dss.orders ord
,dss.ordered_items orditm
,dss.ordered_item_schedules ordsch
WHERE ord.id = in_order_id
AND orditm.order_id = ord.id
AND ordsch.orditm_id = orditm.id;
CURSOR c_inbound(in_orditm_id IN dss.ordered_items.id%TYPE)
IS
SELECT recshp.id recshp_id
,recshp.waybill
,recshp.estimated_freight
,recshp.actual_freight
,recshp.dt_created
FROM dss.built_items bltitm
,dss.received_shipments recshp
WHERE bltitm.orditm_id_rcvd = in_orditm_id
AND recshp.id = bltitm.recshp_id
AND recshp.dt_created BETWEEN TO_DATE('01-JAN-2017','dd-MON-yyyy')
AND TO_DATE('31-DEC-2017','dd-MON-yyyy')
UNION ALL
SELECT recshp.id recshp_id
,recshp.waybill
,recshp.estimated_freight
,recshp.actual_freight
,recshp.dt_created
FROM dss.received_items rcvitm
,dss.received_shipments recshp
WHERE rcvitm.orditm_id_rcvd = in_orditm_id
AND recshp.id = rcvitm.recshp_id
AND recshp.dt_created BETWEEN TO_DATE('01-JAN-2017','dd-MON-yyyy')
AND TO_DATE('31-DEC-2017','dd-MON-yyyy');
v_cust_processed NUMBER := 0;
v_custord_processed NUMBER := 0;
v_orgrole_id_customer dss.org_roles.id%TYPE;
v_estimated_freight_custord adwaram.order_freight.estimated_freight%TYPE;
v_actual_freight_custord adwaram.order_freight.actual_freight%TYPE;
v_orditm_id_core dss.exchange_cores.orditm_id%TYPE;
v_order_id_core dss.orders.id%TYPE;
v_bltitm_id_core dss.po_histories.bltitm_id%TYPE;
v_order_type dss.orders.order_type%TYPE;
v_order_number dss.orders.order_number%TYPE;
v_order_id_xfer dss.orders.id%TYPE;
v_order_id_inbound dss.orders.id%TYPE;
v_orditm_id_po ordered_items.id%TYPE;
--anu
v_calc_freight number:=0;
v_method varchar2(4000);
BEGIN
FOR c_progpcon_rec IN c_progpcon
LOOP
v_cust_processed := v_cust_processed + 1;
SELECT orgrole_id
INTO v_orgrole_id_customer
FROM dss.customers
WHERE id = c_progpcon_rec.cust_id;
FOR c_custord_rec IN c_custord(v_orgrole_id_customer)
LOOP
v_custord_processed := v_custord_processed + 1;
-- outbound customer order
FOR c_outbound_rec IN c_outbound(c_custord_rec.order_id)
LOOP
begin
v_calc_freight:=DSS.PKG_ESTIMATED_FREIGHT.GET_ESTIMATED_FREIGHT
(null,c_outbound_rec.ship_id,v_method);
exception
when others then
v_calc_freight := 0;
end;
INSERT INTO adwaram.order_freight
(order_type
,order_number
,shipper_no
,waybill
,actual_freight
,estimated_freight
,waybill_entered
,order_id
,ship_id
,shptrk_id
,recshp_id
,cust_id
,order_id_cust
,notes
,dt_created)
VALUES
(c_custord_rec.order_type
,c_custord_rec.order_number
,c_outbound_rec.shipper_no
,c_outbound_rec.waybill
,c_outbound_rec.actual_freight
,v_calc_freight--c_outbound_rec.estimated_freight
,c_outbound_rec.dt_created
,c_custord_rec.order_id
,c_outbound_rec.ship_id
,c_outbound_rec.shptrk_id
,NULL
,c_progpcon_rec.cust_id
,c_custord_rec.order_id
,'OUTBOUND CUST ORDER'
,SYSDATE);
END LOOP;
FOR c_ordsch_rec IN c_ordsch(c_custord_rec.order_id)
LOOP
-- get core
BEGIN
SELECT xccore.orditm_id
,pohist.bltitm_id
INTO v_orditm_id_po
,v_bltitm_id_core
FROM dss.exchange_units xcunit
,dss.exchange_cores xccore
,dss.po_histories pohist
WHERE xcunit.ordsch_id = c_ordsch_rec.ordsch_id
AND xccore.xcitm_id = xcunit.xcitm_id
AND pohist.orditm_id(+) = xccore.orditm_id;
IF v_bltitm_id_core IS NOT NULL
THEN
v_order_id_core := dss.pkg_inven.func_get_order(v_bltitm_id_core
,'ORDER_ID');
v_orditm_id_core := dss.pkg_inven.func_get_order(v_bltitm_id_core
,'ORDITM_ID');
ELSE
v_order_id_core := NULL;
END IF;
IF v_order_id_core IS NOT NULL
THEN
-- outbound order for received core (repair order or customer order)
FOR c_outbound_rec IN c_outbound(v_order_id_core)
LOOP
begin
v_calc_freight:=DSS.PKG_ESTIMATED_FREIGHT.GET_ESTIMATED_FREIGHT
(null,c_outbound_rec.ship_id,v_method);
exception
when others then
v_calc_freight := 0;
end;
SELECT order_type
,order_number
INTO v_order_type
,v_order_number
FROM dss.orders
WHERE id = v_order_id_core;
INSERT INTO adwaram.order_freight
(order_type
,order_number
,shipper_no
,waybill
,actual_freight
,estimated_freight
,waybill_entered
,order_id
,ship_id
,shptrk_id
,recshp_id
,cust_id
,order_id_cust
,notes
,dt_created)
VALUES
(v_order_type
,v_order_number
,c_outbound_rec.shipper_no
,c_outbound_rec.waybill
,c_outbound_rec.actual_freight
,v_calc_freight--c_outbound_rec.estimated_freight
,c_outbound_rec.dt_created
,v_order_id_core
,c_outbound_rec.ship_id
,c_outbound_rec.shptrk_id
,NULL
,c_progpcon_rec.cust_id
,c_custord_rec.order_id
,'OUTBOUND '||v_order_type||' ORDER'
,SYSDATE);
END LOOP;
END IF;
-- xfer related to customer order
BEGIN
SELECT ord.id
INTO v_order_id_xfer
FROM dss.orders ord
,dss.ordered_items orditm
WHERE ord.order_type = 'XFER'
AND ord.div_no = c_progpcon_rec.div_no
AND orditm.order_id = ord.id
AND orditm.customer_po = c_custord_rec.customer_po;
FOR c_outbound_rec IN c_outbound(v_order_id_xfer)
LOOP
begin
v_calc_freight:=DSS.PKG_ESTIMATED_FREIGHT.GET_ESTIMATED_FREIGHT
( null,c_outbound_rec.ship_id,v_method);
exception
when others then
v_calc_freight := 0;
end;
SELECT order_type
,order_number
INTO v_order_type
,v_order_number
FROM dss.orders
WHERE id = v_order_id_xfer;
INSERT INTO adwaram.order_freight
(order_type
,order_number
,shipper_no
,waybill
,actual_freight
,estimated_freight
,waybill_entered
,order_id
,ship_id
,shptrk_id
,recshp_id
,cust_id
,order_id_cust
,notes
,dt_created)
VALUES
(v_order_type
,v_order_number
,c_outbound_rec.shipper_no
,c_outbound_rec.waybill
,c_outbound_rec.actual_freight
,v_calc_freight--c_outbound_rec.estimated_freight
,c_outbound_rec.dt_created
,v_order_id_xfer
,c_outbound_rec.ship_id
,c_outbound_rec.shptrk_id
,NULL
,c_progpcon_rec.cust_id
,c_custord_rec.order_id
,'OUTBOUND '||v_order_type||' ORDER'
,SYSDATE);
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND
OR TOO_MANY_ROWS
THEN
NULL;
END;
-- inbound orders associate with exchange - v_orditm_id_core (if ro)
-- v_orditm_id_po (csp po)
IF v_orditm_id_core IS NOT NULL
THEN
FOR c_inbound_rec IN c_inbound(v_orditm_id_core)
LOOP
begin
v_calc_freight:=DSS.PKG_ESTIMATED_FREIGHT.GET_ESTIMATED_FREIGHT
( c_inbound_rec.recshp_id,null,v_method);
exception
when others then
v_calc_freight := 0;
end;
SELECT ord.order_type
,ord.order_number
,ord.id
INTO v_order_type
,v_order_number
,v_order_id_inbound
FROM dss.ordered_items orditm
,dss.orders ord
WHERE orditm.id = v_orditm_id_core
AND ord.id = orditm.order_id;
INSERT INTO adwaram.order_freight
(order_type
,order_number
,shipper_no
,waybill
,actual_freight
,estimated_freight
,waybill_entered
,order_id
,ship_id
,shptrk_id
,recshp_id
,cust_id
,order_id_cust
,notes
,dt_created)
VALUES
(v_order_type
,v_order_number
,NULL
,c_inbound_rec.waybill
,c_inbound_rec.actual_freight
,v_calc_freight--c_inbound_rec.estimated_freight
,c_inbound_rec.dt_created
,v_order_id_inbound
,NULL
,NULL
,c_inbound_rec.recshp_id
,c_progpcon_rec.cust_id
,c_custord_rec.order_id
,'INBOUND '||v_order_type||' ORDER'
,SYSDATE);
END LOOP;
END IF;
IF v_orditm_id_po IS NOT NULL
THEN
FOR c_inbound_rec IN c_inbound(v_orditm_id_po)
LOOP
begin
v_calc_freight:=DSS.PKG_ESTIMATED_FREIGHT.GET_ESTIMATED_FREIGHT
( c_inbound_rec.recshp_id
,NULL
, v_method
);
exception
when others then
v_calc_freight := 0;
end;
SELECT ord.order_type
,ord.order_number
,ord.id
INTO v_order_type
,v_order_number
,v_order_id_inbound
FROM dss.ordered_items orditm
,dss.orders ord
WHERE orditm.id = v_orditm_id_po
AND ord.id = orditm.order_id;
INSERT INTO adwaram.order_freight
(order_type
,order_number
,shipper_no
,waybill
,actual_freight
,estimated_freight
,waybill_entered
,order_id
,ship_id
,shptrk_id
,recshp_id
,cust_id
,order_id_cust
,notes
,dt_created)
VALUES
(v_order_type
,v_order_number
,NULL
,c_inbound_rec.waybill
,c_inbound_rec.actual_freight
,v_calc_freight--c_inbound_rec.estimated_freight
,c_inbound_rec.dt_created
,v_order_id_inbound
,NULL
,NULL
,c_inbound_rec.recshp_id
,c_progpcon_rec.cust_id
,c_custord_rec.order_id
,'INBOUND '||v_order_type||' ORDER'
,SYSDATE);
END LOOP;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND
OR TOO_MANY_ROWS
THEN
NULL;
END;
END LOOP;
END LOOP;
END LOOP;
COMMIT;
dbms_output.put_line(TO_CHAR(v_cust_processed)||' customers processed.');
dbms_output.put_line(TO_CHAR(v_custord_processed)||' customer orders processed.');
END;
/
【问题讨论】:
是的,有很多更快的方法...光标很慢,找到另一种方法。不幸的是,虽然没有时间浏览那个庞大的脚本 你能给我举个例子吗? 你几天前问过这个问题(但看起来你删除了它)。显然你当时没有得到满意的答案,现在你也不会得到。这是一个无法回答的问题。您不能合理地期望陌生人在没有任何业务规则解释的情况下滚动浏览数百行格式不良、陈旧的代码。我们不是来为你做你的工作的。 在您的代码中,您总是逐行处理数据,这基本上是最慢的处理方式。将您的插入转换为INSERT INTO ... SELECT ... FROM ...
。如果这是不可能的(尽管从快速查看您的代码应该没问题)考虑BULK COLLECT INTO
和FORALL
操作。跳过v_cust_processed
和v_custord_processed
处理/输出,你不需要它们。
【参考方案1】:
-
检查所有查询的执行计划,确保它们有效
正如预期的那样
使用 BULK COLLECT 和 FORALL 进行批量处理,如中所述
这个Oracle Magazine Article Steven Feuerstein 可能会有所帮助。
【讨论】:
尝试使用批量收集。出现错误,FOR i1 IN 1 .. c_outbound_tab.count LOOP 开始 -- 批量插入 FORALL i1 IN 1 .. c_outbound_tab.count PLS-00436:实施限制:无法引用 BULK In-BIND 记录表的字段 无法发布所有代码。 -- 填写 pl/sql 表 OPEN c_outbound(c_custord_rec.order_id); FETCH c_outbound BULK COLLECT INTO c_outbound_tab;关闭 c_outbound;以上是关于避免多次插入到oracle表中[关闭]的主要内容,如果未能解决你的问题,请参考以下文章
我是springboot新手,需要在oracle表中插入json数据,避免重复插入