1

我有以下表格

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;
4

4 回答 4

2

这是使用RETURNING INTO子句的绝佳机会,当它与BULK COLLECT结合使用时会非常有用。

为了使用它,您必须设置一个数组来保存locid您要删除的内容。由于locid每个 s 可能有多个 s SKUID,因此您可能必须将每个 s 的数量减少一个以上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为 a forall,但我以前从未这样做过,也找不到您可以这样做的确认。如果可能的话,它看起来像这样:

forall i in t_locid.first .. t_locid.last
   update a2loc
      set locqty = locqty - 1
    where locid = t_locid(i)
          ;

正如Tom Kyte 建议的那样,我强烈建议索引外键;在这种情况下肯定会更好。

于 2012-09-30T14:00:15.357 回答
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;

我不确定您将 locqty 调整为 1 是什么意思。您必须以正确的方式修改更新命令

于 2012-09-30T13:18:03.817 回答
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;
于 2012-09-30T13:15:10.807 回答
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;
于 2012-09-30T14:12:04.233 回答