避免多次插入oracle表

时间:2017-12-28 22:58:49

标签: sql oracle performance plsql sql-insert

**加载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;
            /

1 个答案:

答案 0 :(得分:1)

  1. 检查所有查询的执行计划,确保它们有效 如预期的那样
  2. 使用BULK COLLECT和FORALL进行批量处理,如中所述 这个Oracle Magazine Article由Steven Feuerstein提供帮助。