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

これは、 BULK COLLECTと組み合わせると非常に便利なRETURNING INTO句を使用する絶好の機会です。

これを使用するにlocidは、削除する を保持する配列を設定する必要があります。locidごとに複数の が存在SKUIDする可能性があるため、 ごとに数量を 1 つ以上減らす必要がある場合があります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 が示唆するように、外部キーのインデックス作成を強くお勧めします。この状況では、それは間違いなく良いでしょう。

于 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 に答える