问题是:处理交易并确定对库存的影响。使用光标显示在处理销售,退货和购买后提供原始库存和库存的信息。
我的两张表是:
表一是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
答案 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;