数量增加/减少pl / sql

时间:2016-01-13 15:02:18

标签: plsql oracle11g

我编写了这个程序,旨在根据订单详细信息中的pno和ono单独删除项目。删除的项目将相应地放入表RECORDS和REMOVED_ODETAILS中。订单不止一次购买的一些商品,以及每件商品的购买数量,即数量。我的问题是如何减少订购多次的商品的数量-1,并增加数量EVTY REMOVED_ODETAILS +1?

create or replace PROCEDURE ONE_BY_ONE( ORD_NUM IN NUMBER(5), PRO_NUM IN NUMBER(5), QUANTITY NUMBER(5))
AS
CURSOR CUR1
IS
SELECT * FROM ORDERS 
WHERE ONO = ORD_NUM;

CURSOR CUR2
IS
SELECT * FROM ODETAILS
WHERE PNO = PRO_NUM
AND ONO = P_ONO;

VAL1 CUR1%ROWTYPE;
VAL2 CUR2%ROWTYPE;

BEGIN

OPEN CUR1;
OPEN CUR2;

LOOP
FETCH CUR1 INTO VAL1;
FETCH CUR2 INTO VAL2;

EXIT WHEN CUR1%NOTFOUND;
EXIT WHEN CUR1%NOTFOUND;


IF VAL1.SHIPPED IS NOT NULL THEN
   IF PRO_NUM = VAL2.PNO AND ORD_NUM = VAL2.ONO THEN
       IF ( VAL2.QTY >  QUANTITY) THEN
    FOR R IN (SELECT ONO, PNO FROM REMOVED_ODETAILS) LOOP
  --CODE NOT CHECK TO INSERT OR UPDATE ON REMOVED_ODETAILS
    IF (R.ONO != ORD_NUM AND R.PNO != PRO_NUM) THEN
    INSERT
      INTO REMOVED_ODETAILS
        (
          ONO,
          PNO,
          QTY
        )
        VALUES
        (
          VAR_CUR2.ONO,
          VAR_CUR2.PNO,
          VAR_CUR2.QTY
        );
        ELSE 
      UPDATE REMOVED_ODETAILS SET QTY = QTY - QUANTITY WHERE ONO = ORD_NUM AND 
                                                            PNO =PRO_NUM;
        END IF;
    END LOOP;

      INSERT INTO RECORDS(ID_NUMBER, ONO,CNO,DATE_SEND,CONDITION)
      VALUES(Seq.NEXTVAL, VAL1.ONO,VAL1.CNO,SYSDATE,'SEND BACK');

     ELSIF (VAL2.QTY = QUANTITY ) THEN 
      INSERT INTO RECORDS(ID_NUMBER, ONO,CNO,DATE_SEND,CONDITION)
      VALUES(Seq.NEXTVAL, VAL1.ONO,VAL1.CNO,SYSDATE,'SEND BACK');
     INSERT INTO REMOVED_ODETAILS( ONO, PNO, QTY) 
             VALUES(VAR_CUR2.ONO,VAR_CUR2.PNO, VAR_CUR2.QTY);
      DELETE FROM ODETAILS WHERE ONO = ORD_NUM AND `enter code here`PNO = PRO_NUM;
   END IF;  


       DBMS_OUTPUT.PUT_LINE('Item will be send back ');

        DELETE FROM ORDERS 
        WHERE ONO = ORD_NUM and 
        NOT EXISTS (select 1 from ODETAILS where ONO = ORD_NUM );

ELSIF VAL1.SHIPPED IS NULL THEN
       DBMS_OUTPUT.PUT_LINE('DO NOTHING ');
END IF;

END LOOP;
CLOSE CUR1;
CLOSE CUR2;
END ONE_BY_ONE;

客户

 create table customers (
  cno      number(5) not null primary key,
  cname    varchar2(30),
  street   varchar2(30),
  zip      number(5) references zipcodes,
  phone    char(12));

EMPLOYEES

create table employees (
 eno      number(4) not null primary key, 
 ename    varchar2(30),
 zip      number(5) references zipcodes,
 hdate    date);

订单

create table orders (
  ono      number(5) not null primary key,
  cno      number(5) references customers,
  eno      number(4) references employees,
  received date,
  shipped  date);

ODETAILS

 create table odetails (
  ono      number(5) not null references orders,
  pno      number(5) not null references parts,
  qty      integer check(qty > 0),
  primary key (ono,pno));

记录

create table RECORDS
       id_number  number(5) not null primary key,
       ono        number(5) not null,
       cno        number(5) not null,
       date_send  date,
       condition  varchar22(30));

REMOVED_ODETAILS

create table REMOVED_ODETAILS ( 
      ono      number(5) not null,
      pno      number(5) not null,
      qty      integer check(qty > 0),
      primary key (ono,pno));

BEFORE

订单

    ONO         CNO         ENO     RECEIVED DATE   SHIPPED DATE
  ---------- ---------- ----------  -----------     ---------- 
     1112      7000        1004      02-JAN-16      20-DEC-15 
     1113      12345       2002      10-JAN-16      15-DEC-15
     1114      12345       2002      09-JAN-16      14-DEC-15

ODETAILS

     ONO        PNO         QTY     
  ---------- ---------- ----------  
     1112      12345         3 
     1112      98766         3    
     1113      12345         2
     1114      12345         1

预期答案(给定特定的ono / pno组合时)

记录

   ID_NUMBER       ONO      CNO    DATE_SEND     CONDITION 
  ------------   -------  --------  ----------     --------      
    10001         1112     7000    13-JAN-16     SEND BACK 
    10002         1112     7000    13-JAN-16     SEND BACK
    10003         1112     7000    13-JAN-16     SEND BACK 
    10005         1113     12345    14-JAN-16     SEND BACK
    10006         1114     12345    14-JAN-16     SEND BACK

REMOVED_ODETAILS

     ONO        PNO        QTY
   -------     ------     ------
     1112      12345        2
     1112      98766        1
     1113      12345        1
     1114      12345        1

ODETAILS

     ONO        PNO         QTY
  ---------- ---------- ----------
    1112       12345          1
    1112       98766          2 
    1113       12345          1

订单

     ONO        CNO       ENO      RECEIVED DATE   SHIPPED DATE
  ---------- ---------- ----------  -----------  ---------- 
    1112       7000        1004      02-JAN-16     20-DEC-15 
    1113       12345       2002      10-JAN-16     15-DEC-15

2 个答案:

答案 0 :(得分:0)

以下是我编写程序的方法:

create or replace procedure one_by_one (p_ord_num in number,
                                        p_pro_num in number,
                                        p_qty in number)
is
begin
  insert into records (id_number, ono, cno, date_send, condition)
  select records_seq.nextval,
         o.ono,
         o.cno,
         trunc(sysdate) date_send, -- should include the time? if so, remove the trunc()
         'SEND BACK' condition
  from   orders o
         cross join (select level lvl
                     from   dual
                     connect by level <= p_qty) d
  where  o.ono = p_ord_num
  and    shipped is not null;

  merge into removed_odetails tgt
  using (select p_ord_num ono,
                p_pro_num pno,
                p_qty qty
         from   dual) src
    on (tgt.ono = src.ono and tgt.pno = src.pno)
  when not matched then
    insert (tgt.ono, tgt.pno, tgt.qty)
    values (src.ono, src.pno, src.qty)
  when matched then
    update
    set tgt.qty = tgt.qty + src.qty;

  merge into odetails tgt
  using (select p_ord_num ono,
                p_pro_num pno,
                p_qty qty
         from   dual) src
    on (tgt.ono = src.ono and tgt.pno = src.pno)
  when matched then
    update set tgt.qty = tgt.qty - case when tgt.qty > src.qty then src.qty end
    delete 
    where tgt.qty is null;

  delete from orders
  where ono = p_ord_num
  and   ono not in (select ono
                    from   odetails
                    where  ono = p_ord_num);
end;
/

这是一个测试案例,证明它有效:

drop procedure one_by_one;
drop table removed_odetails;
drop table records;
drop table odetails;
drop table orders;
drop sequence records_seq;

create table orders (
  ono      number(5) not null primary key,
  cno      number(5), --references customers,
  eno      number(4), --references employees,
  received date,
  shipped  date);

 create table odetails (
  ono      number(5) not null references orders,
  pno      number(5) not null, --references parts,
  qty      integer check(qty > 0),
  primary key (ono,pno));

create table records (
       id_number  number(5) not null primary key,
       ono        number(5) not null,
       cno        number(5) not null,
       date_send  date,
       condition  varchar2(30));

create sequence records_seq
 start with 10001
  maxvalue 999999999999999999999999999
  minvalue 1
  nocycle
  cache 20
  noorder;

create table removed_odetails ( 
      ono      number(5) not null,
      pno      number(5) not null,
      qty      integer check(qty > 0),
      primary key (ono,pno));

insert into orders (ono, cno, eno, received, shipped)
select 1112 ono, 7000 cno, 1004 eno, to_date('02/01/2016', 'dd/mm/yyyy') received, to_date('20/12/2015', 'dd/mm/yyyy') shipped from dual union all
select 1113 ono, 12345 cno, 2002 eno, to_date('10/01/2016', 'dd/mm/yyyy') received, to_date('15/12/2015', 'dd/mm/yyyy') shipped from dual union all
select 1114 ono, 12345 cno, 2002 eno, to_date('09/01/2016', 'dd/mm/yyyy') received, to_date('14/12/2015', 'dd/mm/yyyy') shipped from dual;

insert into odetails (ono, pno, qty)
select 1112 ono, 12345 pno, 3 qty from dual union all
select 1112 ono, 98766 pno, 3 qty from dual union all
select 1113 ono, 12345 pno, 2 qty from dual union all
select 1114 ono, 12345 pno, 1 qty from dual;

commit;

-- now run the procedure for all rows in removed_odetails:

begin
  for rec in (select 1112 ono, 12345 pno, 2 qty from dual union all
              select 1112 ono, 98766 pno, 1 qty from dual union all
              select 1113 ono, 12345 pno, 1 qty from dual union all
              select 1114 ono, 12345 pno, 1 qty from dual)
  loop
    one_by_one(p_ord_num => rec.ono,
               p_pro_num => rec.pno,
               p_qty => rec.qty);
  end loop;
  commit;
end;
/

select * from orders;

       ONO        CNO        ENO RECEIVED   SHIPPED   
---------- ---------- ---------- ---------- ----------
      1112       7000       1004 02/01/2016 20/12/2015
      1113      12345       2002 10/01/2016 15/12/2015

select * from odetails;

       ONO        PNO        QTY
---------- ---------- ----------
      1112      12345          1
      1112      98766          2
      1113      12345          1

select * from removed_odetails;

       ONO        PNO        QTY
---------- ---------- ----------
      1112      98766          1
      1112      12345          2
      1114      12345          1
      1113      12345          1

select * from records;

 ID_NUMBER        ONO        CNO DATE_SEND  CONDITION                     
---------- ---------- ---------- ---------- ------------------------------
     10001       1112       7000 14/01/2016 SEND BACK                     
     10002       1112       7000 14/01/2016 SEND BACK                     
     10003       1112       7000 14/01/2016 SEND BACK                     
     10004       1113      12345 14/01/2016 SEND BACK                     
     10005       1114      12345 14/01/2016 SEND BACK                     

begin
  for rec in (select 1112 ono, 98766 pno, 1 qty from dual)
  loop
    one_by_one(p_ord_num => rec.ono,
               p_pro_num => rec.pno,
               p_qty => rec.qty);
  end loop;
  commit;
end;
/

select * from orders;

       ONO        CNO        ENO RECEIVED   SHIPPED   
---------- ---------- ---------- ---------- ----------
      1112       7000       1004 02/01/2016 20/12/2015
      1113      12345       2002 10/01/2016 15/12/2015

select * from odetails;

       ONO        PNO        QTY
---------- ---------- ----------
      1112      12345          1
      1112      98766          1
      1113      12345          1

select * from removed_odetails;

       ONO        PNO        QTY
---------- ---------- ----------
      1112      98766          2
      1112      12345          2
      1114      12345          1
      1113      12345          1

select * from records;

 ID_NUMBER        ONO        CNO DATE_SEND  CONDITION                     
---------- ---------- ---------- ---------- ------------------------------
     10001       1112       7000 14/01/2016 SEND BACK                     
     10002       1112       7000 14/01/2016 SEND BACK                     
     10003       1112       7000 14/01/2016 SEND BACK                     
     10004       1113      12345 14/01/2016 SEND BACK                     
     10005       1114      12345 14/01/2016 SEND BACK                     
     10006       1112       7000 14/01/2016 SEND BACK   
是的,你看到上面的测试用例?这是您应该提前提供的信息类型,以避免浪费时间让志愿者帮助您......免费。当你发布未来的问题时,请把它带到船上!

答案 1 :(得分:0)

这是一个工作(好吧,似乎每个调用只添加一行ono / pno组合到记录表中,而不是对应于被删除数量的行数)代码版本:

create or replace procedure one_by_one( ord_num in number, pro_num in number, quantity number)
as
  cursor cur1
  is
  select * from orders 
  where ono = ord_num;

  cursor cur2
  is
  select * from odetails
  where pno = pro_num
  and   ono = ord_num;

  val1 cur1%rowtype;
  val2 cur2%rowtype;

begin

  open cur1;
  open cur2;

  loop
    fetch cur1 into val1;
    fetch cur2 into val2;

    exit when cur1%notfound;
    exit when cur1%notfound;

    if val1.shipped is not null then
--      if pro_num = val2.pno and ord_num = val2.ono then -- totally unnecessary, since you already did that check as part of the cursor!
      if (val2.qty > quantity) then
        merge into removed_odetails tgt
        using (select ord_num ono,
                      pro_num pno,
                      quantity qty
               from   dual) src
          on (tgt.ono = src.ono and tgt.pno = src.pno)
        when not matched then
          insert (tgt.ono, tgt.pno, tgt.qty)
          values (src.ono, src.pno, src.qty)
        when matched then
          update
          set tgt.qty = tgt.qty + src.qty;

        update odetails
        set    qty = qty - quantity
        where  ono = ord_num
        and    pno = pro_num;

        insert into records(id_number, ono,cno,date_send,condition)
        values(records_seq.nextval, val1.ono,val1.cno,sysdate,'SEND BACK');

      elsif (val2.qty = quantity ) then 
        insert into records(id_number, ono,cno,date_send,condition)
        values (records_seq.nextval, val1.ono,val1.cno,sysdate,'SEND BACK');

        insert into removed_odetails( ono, pno, qty) 
               values(val2.ono,val2.pno, val2.qty);

        delete from odetails where ono = ord_num and pno = pro_num;
      end if;  

      dbms_output.put_line('Item will be send back ');

      delete from orders 
      where ono = ord_num
      and   not exists (select null from odetails where ono = ord_num);

    elsif val1.shipped is null then
      dbms_output.put_line('DO NOTHING ');
    end if;
  end loop;

  close cur1;
  close cur2;
end one_by_one;
/

当你试图检查remove_odetails表中是否已存在某行时,你试图重新发明MERGE语句,所以我所做的就是删除游标for循环并拥有而是改为使用merge语句(并将removed_odetails表的更新更改为更新odetails表)。

我不建议这个特定的解决方案;它比我提供的其他解决方案简单得多。如果您需要在将来的任何时候维护此代码,您将诅咒自己! (我们都去过那里......)

相关问题