PL/SQL实例讲解(一)

来源:互联网 发布:小键盘 软件 编辑:程序博客网 时间:2024/05/22 09:01

题目要求:某加工厂发货规则是:每车发货480件,周六周日不发货,供货期间除了最后一批货外其余只能整车发货。

举个例子:某厂商需求三天货,周四需要供货300,周五需要供货200,周六需要供货400,下周一需要供货200。

原发货表如下:

SHIP_DATE SHIP_QTY PLAN_TYPE 2016-12-01 300 OLD 2016-12-02 200 OLD 2016-12-03 400 OLD 2016-12-05 200 OLD

按照要求不满480件也要发货480,那么周四发货480件,相当于多发了180,多发的量计入周五该发的数量,相当于周五只需要20件就够了。但是周六不发货,所以周六的货需要提前发,并入周五。考虑到下周一还需要货,那么还得按照整车发货要求来,周五也发480件,相当于发了下周一的60件,而整个供货期到周一截止,那么周一发货120即可。

所以实际发货清单如下:

SHIP_DATE SHIP_QTY PLAN_TYPE 2016-12-01 300 OLD 2016-12-01 480 NEW 2016-12-02 200 OLD 2016-12-02 480 NEW 2016-12-03 400 OLD 2016-12-05 200 OLD 2016-12-05 120 NEW

相信题意应该明确了。

可以简单思考一下,如何在程序中考虑这些因素。有两个思路:

第一个:把周六周日的数据移到周五(不是说周六日不让发货吗,那就当成是周五要发的货),再进行发货整车计算。

第二个:先不管周六日不让发货这个规则,先按照整车必须480来计算每天需要的发货量。再将周六日要发的货移到周五即可。

CREATE OR REPLACE PROCEDURE ship_plan IS  l_qty      NUMBER := 0;  l_last_day DATE;BEGIN--process_data游标中放置了按照日期排序的hand_ship_plan表  FOR process_data IN (SELECT hsp.ship_date,                              hsp.ship_qty,                              to_char(hsp.ship_date, 'D') week                         FROM hand_ship_plan hsp                        ORDER BY hsp.ship_date) LOOP    IF process_data.week NOT IN ('1', '7') THEN    --如果游标取到日期不是周六和周日,进行插入操作,相当于对周一到周五的数据进行了复写,将type值变为new      INSERT INTO hand_ship_plan        (ship_date, ship_qty, plan_type)      VALUES        (process_data.ship_date, process_data.ship_qty, 'NEW');    ELSE    --否则(如果游标取到的日期是周六和周日)进行更新操作,更新的是哪一天?由decode判断  如果是周日,让周日那天减2,如果是周六,让周六那天减1,确保日期为周五,将运货量加在周五里      UPDATE hand_ship_plan hsp         SET hsp.ship_qty = nvl(hsp.ship_qty, 0) + process_data.ship_qty       WHERE hsp.ship_date =             process_data.ship_date - decode(process_data.week, 1, 2, 1);    --如果没有语句受到影响(意味着周五没有发货任务)  所以上边的更新操作没有成功,那么直接将周六日插入新建的周五中      IF SQL%NOTFOUND THEN        INSERT INTO hand_ship_plan          (ship_date, ship_qty, plan_type)        VALUES          (process_data.ship_date - decode(process_data.week, 1, 2, 1),           process_data.ship_qty,           'NEW');      END IF;    END IF;  --至此,将周六周日的数据移到周五 完成  END LOOP;--进行第二步操作,process_new游标先取到所有 类型 为 ‘new’的 并且按照日期排序的 条目 及 ROWID 类型为‘new’的只有周一到周五  FOR process_new IN (SELECT ROWID row_id, hsp.*                        FROM hand_ship_plan hsp                       WHERE hsp.plan_type = 'NEW'                       ORDER BY hsp.ship_date) LOOP    --l_qty变量是为了记录当多发的量   当l_qty大于当日该发的量,此时删除那天的‘new’记录    IF l_qty >= process_new.ship_qty THEN      DELETE FROM hand_ship_plan hsp WHERE ROWID = process_new.row_id;      l_qty := l_qty - process_new.ship_qty;    ELSE    --计算每天要发货的数量  ceil向上取整  先算个数  再算数量      UPDATE hand_ship_plan hsp         SET hsp.ship_qty =             ceil((process_new.ship_qty - l_qty) / 480) * 480       WHERE ROWID = process_new.row_id;    --更新多发的货      l_qty      := ceil((process_new.ship_qty - l_qty) / 480) * 480 -                    (process_new.ship_qty - l_qty);      l_last_day := process_new.ship_date;    END IF;  END LOOP;--当到最后一天时  发货剩余的数量  IF l_qty > 0 THEN    UPDATE hand_ship_plan hsp       SET hsp.ship_qty = hsp.ship_qty - l_qty     WHERE hsp.plan_type = 'NEW'       AND hsp.ship_date = l_last_day;  END IF;END;

具体过程程序的注释都有解释。大家可以自己见表尝试。

0 0