执行删除并更新其他表中的相应行

时间:2012-09-30 12:48:50

标签: sql oracle plsql cursor oracle11g

我有以下表格

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 个答案:

答案 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;