避免多次插入到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 INTOFORALL 操作。跳过v_cust_processedv_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表中[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

避免在 Oracle 过程中频繁调用同一视图

我是springboot新手,需要在oracle表中插入json数据,避免重复插入

Oracle MERGE语句

Oracle中插入数据

oracle数据库中怎么能避免相同的数据插入数据库多遍?sql语句怎么处理呢?

Oracle 流水线表函数并将结果插入到 Oracle 表中