pl / sql嵌套循环

时间:2012-10-11 01:32:02

标签: oracle plsql

如何使用items表显示数据库中的所有记录?我当前的查询显示项目894的信息。我尝试使用循环,但没有运气。

我有两个表,库存和itemid。其中itemid具有项目编号和描述,库存表中包含项目的信息,例如大小,颜色,价格和库存数量。

 set serveroutput on
 DECLARE
    current_item    number(8);      
    totalvalue      number(8,2);
    description     varchar2(50);
    item_id         number(3);


    CURSOR Inventory_Info IS       
      SELECT 
         itemsize
        ,color
        ,curr_price
        ,qoh
        ,curr_price*qoh as Total
    FROM inventory
     WHERE itemid=Current_item;



BEGIN

    current_item:=894;
    totalvAlue:=0;  


    SELECT 
     itemdesc, itemid         
       INTO description, item_id
    FROM item
      WHERE itemid=current_item;

    DBMS_OUTPUT.PUT_LINE('Item ID: ' || TO_CHAR(item_id) || ' Item Description: ' || description);

    OPEN Inventory_Info;
    LOOP
            Fetch Inventory_Info INTO Inventory_rocord;
            EXIT WHEN Inventory_Info%NOTFOUND;

     DBMS_OUTPUT.PUT_LINE('Size: ' || Inventory_record.itemsize);
     DBMS_OUTPUT.PUT_LINE('Color: ' || Inventory_record.color);
     DBMS_OUTPUT.PUT_LINE('Price: ' || Inventory_record.curr_price);
     DBMS_OUTPUT.PUT_LINE('QOH: ' || Inventory_record.qoh);
     DBMS_OUTPUT.PUT_LINE('Value: ' || Inventory_record.total);

     TotalValue:=TotalValue + Inventory_record.total;

     End Loop;

     DBMS_OUTPUT.PUT_LINE('TOTAL VALUE: ' || TotalValue);
 Close Inventory_Info;

    EXCEPTION
       WHEN NO_DATA_FOUND THEN                      
       DBMS_OUTPUT.PUT_LINE('No inventory for Item No. '|| current_item);
    WHEN OTHERS THEN                             
       DBMS_OUTPUT.PUT_LINE('Error Message: '|| SQLERRM);

 END;

4 个答案:

答案 0 :(得分:4)

如果我们暂时忘记格式化,可以使用游标for循环更简单地完成。

set serveroutput ON
DECLARE
BEGIN
  FOR item_rec IN (SELECT itemdesc, itemid         
                     FROM item
                  ) LOOP
    DBMS_OUTPUT.PUT_LINE('Item ID: ' || TO_CHAR(item_rec.itemid) 
                             || ' Item Description: ' || item_rec.itemdesc);                      

    FOR Inventory_record IN (SELECT itemsize
                                  , color
                                  , curr_price
                                  , qoh 
                                  , curr_price*qoh AS Total
                               FROM inventory
                              WHERE itemid = item_rec.itemid
                            ) LOOP

      DBMS_OUTPUT.PUT_LINE('Size: ' || Inventory_record.itemsize);
      DBMS_OUTPUT.PUT_LINE('Color: ' || Inventory_record.color);
      DBMS_OUTPUT.PUT_LINE('Price: ' || Inventory_record.curr_price);
      DBMS_OUTPUT.PUT_LINE('QOH: ' || Inventory_record.qoh);
      DBMS_OUTPUT.PUT_LINE('Value: ' || Inventory_record.total);

      TotalValue:= TotalValue + Inventory_record.total;

    END LOOP;      
  END LOOP;
END;

答案 1 :(得分:1)

您使用单独的SELECT..INTO来抓取itemid,但是您将itemid分配给单个值,并且不会更改它。

查看您的查询,您可以将itemid提取移动到游标&加入2个表。您将项目提取到inventory_record,但我没有看到任何地方的定义/声明。

这里我声明一个记录类型变量,包括你要获取的内容,打开游标,将细节提取到该游标中。由于没有明确的where条件,它将在item&之间执行内连接。库存表&获取与连接条件匹配的所有行。

set serveroutput ON

DECLARE
    TYPE inventory_rec IS RECORD (
      itemid item.itemid%TYPE,
      itemdesc item.itemdesc%TYPE,
      itemsize inventory.itemsize%TYPE,
      color inventory.color%TYPE,
      curr_price inventory.curr_price%TYPE,
      qoh inventory.qoh %TYPE,
      total inventory.curr_price%TYPE); -- record type to hold what cursor will be fetching

    inventory_record INVENTORY_REC;
    current_item     NUMBER(8);
    totalvalue       NUMBER(8, 2);
    description      VARCHAR2(50);
    item_id          NUMBER(3);

    CURSOR inventory_info IS
      SELECT itemid,
             itemdesc,
             itemsize,
             color,
             curr_price,
             qoh,
             curr_price * qoh AS Total
      FROM   inventory
             join item USING (itemid);
-- join item & inventory, so that it shows listings for all items present in inventory

BEGIN

    OPEN inventory_info;

    LOOP
        FETCH inventory_info INTO inventory_record;
        EXIT WHEN inventory_info%NOTFOUND;
        dbms_output.Put_line('Current item: '
                             || inventory_record.itemdesc);
        dbms_output.Put_line('Size: '
                             || inventory_record.itemsize);
        dbms_output.Put_line('Color: '
                             || inventory_record.color);
        dbms_output.Put_line('Price: '
                             || inventory_record.curr_price);
        dbms_output.Put_line('QOH: '
                             || inventory_record.qoh);
        dbms_output.Put_line('Value: '
                             || inventory_record.total);

        totalvalue := totalvalue + inventory_record.total;
    END LOOP;

    dbms_output.Put_line('TOTAL VALUE: '
                         || totalvalue);

    CLOSE inventory_info;
EXCEPTION
    WHEN no_data_found THEN
      dbms_output.Put_line('No inventory for Item No. '
                           || current_item);
    WHEN OTHERS THEN
      dbms_output.Put_line('Error Message: '
                           || SQLERRM);
END; 

答案 2 :(得分:1)

如果它只是一个报告(似乎是)。请考虑使用sql*plus报告格式化命令以您希望的方式显示查询的输出。

以下是一个例子:

SQL> create table Items(
  2    i_num number,
  3    i_descr varchar2(101),
  4    i_size varchar2(3),
  5    i_price number,
  6    i_qoh number
  7  );

Table created

SQL> create table Inventories(
  2    id number,
  3    i_num number
  4  );

Table created

SQL> insert into items(i_num,i_size,i_price,i_qoh,i_descr)
  2    select 1, 'S', 123, 25, 'Item_1' from dual union all
  3    select 2, 'L', 424, 12, 'Item_1' from dual union all
  4    select 4, 'S', 45,  54, 'Item_4' from dual union all
  5    select 5, 'S', 78,  54, 'Item_4' from dual union all
  6    select 6, 'S', 123, 22, 'Item_5' from dual union all
  7    select 7, 'S', 127, 65, 'Item_5' from dual
  8  ;

6 rows inserted

SQL> commit;

Commit complete

SQL> insert into inventories
  2    select i_num, i_num
  3      from items;

6 rows inserted

SQL> commit;

Commit complete

现在我们的报告:

SQL> column i_descr format a10
SQL> column i_size  format a3
SQL> column i_price format 99999
SQL> column i_qoh   format 99999
SQL> column value   format 99999
SQL> break on i_descr skip 2
SQL> compute sum label 'Total: ' of value on i_descr;

SQL> select itm.i_descr
  2       , itm.i_size
  3       , itm.i_price
  4       , itm.i_qoh
  5       , sum(i_price*i_qoh) Value
  6   from inventories inv
  7   join items itm on (inv.i_num = itm.i_num)
  8   group by itm.i_num
  9          , itm.i_descr
 10          , itm.i_size
 11          , itm.i_price
 12          , itm.i_qoh
 13   order by i_descr, i_price;


I_DESCR    I_S    I_PRICE  I_QOH  VALUE
---------- --- ---------- ------ ------
Item_1     S          123     25   3075
           L          424     12   5088
**********                       ------
Total:                             8163


Item_4     L           45     54   2430
           S           78     54   4212
**********                       ------
Total:                             6642


Item_5     S          123     22   2706
           L          127     65   8255
**********                       ------
Total:                            10961



6 rows selected.  

答案 3 :(得分:1)

请勿使用嵌套查找,请使用加入。数据库非常擅长连接,并且集合操作的性能比逐行处理要好得多。

此外,在大多数情况下,您不需要声明游标和变量。使用游标循环让Oracle为您做繁重的工作。

set serveroutput on  
DECLARE     
    totalvalue      number(8,2);
BEGIN      
    totalvAlue:=0;
    FOR inv_itm_rec IN (       
        SELECT    itm.itemid
            , itm.itemdesc
            , inv.itemsize         
            , inv.color         
            ,inv.curr_price         
            ,inv.qoh         
            ,inv.curr_price*inv.qoh as Total     
        FROM inventory  inv   
        JOIN item itm
            ON itm.itemid=inv.itemid
       ) 
     LOOP   
    DBMS_OUTPUT.PUT_LINE('ItemId: ' || inv_itm_rec.itemid);
    DBMS_OUTPUT.PUT_LINE('Description: ' || inv_itm_rec.itemdesc);
    DBMS_OUTPUT.PUT_LINE('Size: ' || inv_itm_rec.itemsize);
    DBMS_OUTPUT.PUT_LINE('Color: ' || inv_itm_rec.color);
    DBMS_OUTPUT.PUT_LINE('Price: ' || inv_itm_rec.curr_price);
    DBMS_OUTPUT.PUT_LINE('QOH: ' || inv_itm_rec.qoh);
    DBMS_OUTPUT.PUT_LINE('Value: ' || inv_itm_rec.total);
    TotalValue:=TotalValue + inv_itm_rec.total;
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('TOTAL VALUE: ' || TotalValue);
END;

注意,此解决方案假定evry ITEM确实具有匹配的INVENTORY记录。如果数据模型允许其他任何情况,那将是一个朗姆酒旧仓库应用程序。