我有以下表格
CREATE TABLE A2SKU
(
SKUID NUMBER NOT NULL,
SKUNAME VARCHAR2(20),
SKUQTY NUMBER,
CONSTRAINT A2SKU_PK PRIMARY KEY (SKUID)
);
CREATE TABLE A2LOC
(
LOCID NUMBER NOT NULL,
LOCNAME VARCHAR2(20),
LOCQTY NUMBER,
MAXQTY NUMBER,
CONSTRAINT A2LOC_PK PRIMARY KEY (LOCID)
);
Create Table A2BOX (
boxId NUMBER Primary Key,
skuId NUMBER,
locId NUMBER,
constraint FK_A2BOX_SKUID foreign key (skuid) references A2SKU,
constraint FK_A2BOX_LOCID foreign key (locid) references A2LOC
);
CREATE SEQUENCE A2BOXSEQ;
我想从A2Box表中删除所有带有匹配SKU的框,并将每个框的A2Loc表中匹配位置的LocQty调整为1
如何使用存储过程执行此操作。
我尝试了自己并想出了这个
create or replace procedure A2DeleteSKU
(
pskuid IN number
)
AS
CURSOR row_cursor IS
SELECT boxid,locid from A2BOX where skuid = pskuid;
skuid_count Number;
skuid_check exception;
sku_rec row_cursor%rowtype;
Begin
select count(*) into skuid_count from A2SKU where skuid = pskuid;
if skuid_count <1 then
raise skuid_check;
End If;
FOR sku_rec in row_cursor
LOOP
delete from a2box where boxid = sku_rec.boxid;
update A2LOC set locqty = locqty -1 where locid = sku_rec.locid;
END LOOP;
delete from A2SKU where skuid =pskuid;
commit;
Exception
When skuid_check then
RAISE_APPLICATION_ERROR(-20014, 'Delete Box failed. Boxid does not exist: '||TO_CHAR(pskuid));
When others then
raise;
End A2DeleteSku;
答案 0 :(得分:2)
这是使用RETURNING INTO子句的绝佳机会,当与BULK COLLECT结合使用时,它非常有用。
要使用此功能,您必须设置一个数组来保存要删除的locid
。由于每个locid
可能有多个SKUID
,因此您可能需要每locid
个数量减少一个以上。
create or replace procedure remove_boxes ( PSKUID number ) is
-- Set up an array to hold the deletes
type t__locid is table of a2loc.locid%type index by binary_integer;
t_locid t__locid;
begin
-- Delete the rows and return the deleted locids
delete from a2box
where skuid = PSKUID
returning locid
bulk collect into t_locid
;
for i in t_locid.first .. t_locid.last loop
update a2loc
set locqty = locqty - 1
where locid = t_locid(i)
;
end loop;
end remove_boxes;
/
您可以将for .. loop
更改为forall
,但我之前从未这样做过,也无法找到确认信息。如果可能,它将如下所示:
forall i in t_locid.first .. t_locid.last
update a2loc
set locqty = locqty - 1
where locid = t_locid(i)
;
作为Tom Kyte suggests我强烈建议索引外键;在这种情况下肯定会更好。
答案 1 :(得分:1)
CREATE PROCEDURE remove_boxes(pp_skuId NUMBER) IS
BEGIN
UDPATE a2loc SET locqty = locqty - 1
WHERE locid IN (SELECT locid FROM a2box
WHERE skuId = pp_skuId);
DELETE FROM a2box
WHERE skuId = pp_skuId;
END;
我不确定你对adjust locqty的意思是1.你必须以正确的方式修改更新命令
答案 2 :(得分:0)
根据我的理解,A2LOC上的LOCQTY列表示具有相应locid的框的摘要,并且您希望在移除框时调整它。因此,请检查以下代码:
create or replace procedure adjustLoc(p_skuid number) is
begin
-- Adjusts the locqty value
update A2LOC loc
set LOCQTY = LOCQTY -1
where exists(select 1
from A2BOX box
where box.locid = loc.locid
and box.skuid = p_skuid);
-- Removes all sku matching boxes
Delete A2BOX
where skuid = p_skuid;
end;
答案 3 :(得分:0)
create or replace procedure A2DeleteSKU
(
pskuid IN number
)
AS
CURSOR row_cursor IS
SELECT boxid,locid from A2BOX where skuid = pskuid;
skuid_count Number;
skuid_check exception;
sku_rec row_cursor%rowtype;
Begin
select count(*) into skuid_count from A2SKU where skuid = pskuid;
if skuid_count <1 then
raise skuid_check;
End If;
FOR sku_rec in row_cursor
LOOP
delete from a2box where boxid = sku_rec.boxid;
update A2LOC set locqty = locqty -1 where locid = sku_rec.locid;
END LOOP;
delete from A2SKU where skuid =pskuid;
commit;
Exception
When skuid_check then
RAISE_APPLICATION_ERROR(-20014, 'Delete Box failed. Boxid does not exist: '||TO_CHAR(pskuid));
When others then
raise;
End A2DeleteSku;