使用库存和事务表的PL / SQL游标

时间:2015-12-01 02:42:14

标签: oracle plsql

问题是:处理交易并确定对库存的影响。使用光标显示在处理销售,退货和购买后提供原始库存和库存的信息。

我的两张表是:

表一是itemid,itemname和quanity。

ITEM ITEMNAME                     QUANITY
---- ------------------------- ----------
1111 Computer                          50
2222 TV                                10
3333 Camera                            35
4444 Phone                             40

表2是itemid,itemname,代码(s = sale,r = return,p =购买),itemsmoved(参考代码...示例1111已售出2)

ITEM ITEMNAME                  C ITEMSMOVED
---- ------------------------- - ----------
1111 Computer                  S          2
2222 TV                        S          5
3333 Camera                    S         15
4444 Phone                     S          7
1111 Computer                  P         10
2222 TV                        R          2
3333 Camera                    P         20
4444 Phone                     R          3

我还创建了一个要插入的表格:

SQL> create table updatedinv
  2  (itemid varchar2(4),
  3  itemname varchar2(15),
  4  orginv number(4),
  5  updatedinv number(4));

我的PL / SQL代码是:

SET SERVEROUTPUT ON
DECLARE
  v_idno      inventory.itemid%TYPE;
  v_name      inventory.itemname%TYPE;
  v_quantity  inventory.quanity%TYPE;
  v_tidno     transaction.itemid%TYPE;
  v_code      transaction.code%TYPE;
  v_move      transaction.itemsmoved%TYPE;
  v_updated   updatedinv.updatedinv%TYPE;
  CURSOR inventory_cursor IS
     SELECT itemid, itemname, quanity FROM inventory
     ORDER BY itemid;
  CURSOR transaction_cursor IS
     SELECT itemid, code, itemsmoved FROM transaction
     WHERE v_idno = itemid
     ORDER BY itemid;
  BEGIN
     OPEN inventory_cursor;
     LOOP
       FETCH inventory_cursor INTO v_idno, v_name, v_quantity;
       EXIT WHEN inventory_cursor%NOTFOUND;
       IF transaction_cursor%ISOPEN THEN
         CLOSE transaction_cursor;
       END IF;
       OPEN transaction_cursor;
       v_updated := 0;
       LOOP
         FETCH transaction_cursor INTO v_tidno, v_code, v_move;
         EXIT WHEN transaction_cursor%NOTFOUND;
         IF v_code = 'S' THEN
         v_updated := v_quantity - v_move;
         END IF;
         IF v_code = 'R' THEN
         v_updated := v_quantity + v_move;
         END IF;
         IF v_code = 'P' THEN
         v_updated := v_quantity + v_move;
         END IF;
                END LOOP;
       INSERT into updatedinv 
          VALUES(v_idno, v_name, v_quantity, v_updated);
       CLOSE transaction_cursor;
     END LOOP;
     CLOSE inventory_cursor;
END;
/
SET SERVEROUTPUT OFF

正在计算代码P和R而不是S,销售在购买或退货之前没有被滥用:

SQL> @ loop1

PL/SQL procedure successfully completed.

SQL> select *
  2  from updatedinv;

ITEM ITEMNAME            ORGINV UPDATEDINV
---- --------------- ---------- ----------
1111 Computer                50         60
2222 TV                      10         12
3333 Camera                  35         55
4444 Phone                   40         43

结果应如下所示:

SQL> select *
  2  from updatedinv;

ITEM ITEMNAME            ORGINV UPDATEDINV
---- --------------- ---------- ----------
1111 Computer                50         58
2222 TV                      10          7
3333 Camera                  35         40
4444 Phone                   40         36

2 个答案:

答案 0 :(得分:1)

你写的方式很复杂。您可以使用隐式游标来避免大量编码。

DECLARE
   l_updatedinv updatedinv.updatedinv%type;
BEGIN
   FOR i IN (select * from inventory order by itemid)
   LOOP
       l_updatedinv := i.quanity;
       FOR j IN (select * from transaction where itemid = i.itemid)
       LOOP
       l_updatedinv := 
           case when j.code = 'S' then l_updatedinv - j.itemsmoved
           when j.code in ('P', 'R') then l_updatedinv + j.itemsmoved
           end;
      END LOOP;
   INSERT into updatedinv 
      VALUES(i.itemid, i.itemname, i.quanity, l_updatedinv);
   END LOOP;
END;
/

答案 1 :(得分:0)

嗨如果我理解你正确提问你的代码问题就在这行

v_updated := v_quantity - v_move;

每次进行循环时,都会从v_quantity中添加/减去(从不更改),因此它只会有效地处理最后一次事务。

通过在循环之前将v_updated设置为等于v_quantity然后在循环期间仅使用v_updated进行计算来查看下面的修改循环,您应该得到准确的结果。

 OPEN inventory_cursor;
 LOOP
   FETCH inventory_cursor INTO v_idno, v_name, v_quantity;
   EXIT WHEN inventory_cursor%NOTFOUND;
   IF transaction_cursor%ISOPEN THEN
     CLOSE transaction_cursor;
   END IF;
   v_updated := v_quantity; -- Added line
   OPEN transaction_cursor;
   v_updated := 0;
   LOOP
     FETCH transaction_cursor INTO v_tidno, v_code, v_move;
     EXIT WHEN transaction_cursor%NOTFOUND;
     IF v_code = 'S' THEN
     v_updated := v_updated - v_move; -- changed v_quantity to v_updated
     END IF;
     IF v_code = 'R' THEN
     v_updated := v_updated  + v_move; -- changed v_quantity to v_updated
     END IF;
     IF v_code = 'P' THEN
     v_updated := v_updated + v_move; -- changed v_quantity to v_updated
     END IF;
            END LOOP;
   INSERT into updatedinv 
      VALUES(v_idno, v_name, v_quantity, v_updated);
   CLOSE transaction_cursor;
 END LOOP;
 CLOSE inventory_cursor;