在pl sql中的FOR循环语句中的表中插入值

时间:2015-01-15 13:43:07

标签: sql oracle plsql

我想从i = 1运行循环到i = 12并插入M_1,M_2等的每个值,直到M_Maintenance表中的M_12。我已经尝试过但它不起作用。请帮帮我。 我试过的代码是: -

BEGIN
   FOR i IN 1 .. 12
   LOOP
      DECLARE
         M_i               NUMBER;
         MONTH_i_COUNT     NUMBER;
         M_i_Maintenance   NUMBER;
         MONTH_i_SUM       NUMBER;
      BEGIN
         SELECT   ROUND (
                     ( ( (SELECT   SUM (MONTH_i_COUNT)
                            FROM   XXBAXY.XXBAXY_BREAKDOWN_TAB
                           WHERE   LOSS_CAT = 'Maintenance Related Losses')
                        + (SELECT   MONTH_i_COUNT
                             FROM   XXBAXY.XXBAXY_BREAKDOWN_TAB
                            WHERE   LOSS_CAT = 'Maintenance Related Losses'
                                    AND description = 'SAFTY SHEET PRO. ')
                        - (SELECT   MONTH_i_COUNT
                             FROM   XXBAXY.XXBAXY_BREAKDOWN_TAB
                            WHERE   LOSS_CAT = 'Maintenance Related Losses'
                                    AND description =
                                          'PREVENTIVE MAINTENANCE '))
                      / (SELECT   MONTH_i_SUM FROM XXBAXY.XXBAXY_ATTR_SUM_TAB))
                     * 100,
                     3
                  )
           INTO   M_i
           FROM   DUAL;
      EXCEPTION
         WHEN ZERO_DIVIDE
         THEN
            M_i := 0;
      END;
      INSERT INTO M_Maintenance (M_i_Maintenance)
        VALUES   (M_i);
   END LOOP;
END;

2 个答案:

答案 0 :(得分:1)

让我们首先让您的查询更容易阅读和更好的演绎,如果我不会误解它应该是这个:

SELECT ROUND(
    SUM(CASE description
    WHEN 'SAFTY SHEET PRO. ' THEN 2*MONTH_i_COUNT
    WHEN 'PREVENTIVE MAINTENANCE ' THEN -MONTH_i_COUNT
    ELSE MONTH_i_COUNT
    END) / MIN(MONTH_i_SUM) *100, 3)
FROM XXBAXY.XXBAXY_BREAKDOWN_TAB
    CROSS JOIN XXBAXY.XXBAXY_ATTR_SUM_TAB 
WHERE LOSS_CAT = 'Maintenance Related Losses'

在这种情况下,您的PL / SQL代码可能如下所示(跳过异常处理程序):

DECLARE
    m NUMBER;
    sqlstr VARCHAR2(1000);

BEGIN
    FOR i IN 1..12 LOOP           
        sqlstr := 
        'SELECT ROUND( '
        '   SUM(CASE description '
        '   WHEN ''SAFTY SHEET PRO. '' THEN 2*MONTH_'||i||'_COUNT '
        '   WHEN ''PREVENTIVE MAINTENANCE '' THEN -MONTH_'||i||'_COUNT '
        '   ELSE MONTH_'||i||'_COUNT '
        '   END) / MIN(MONTH_'||i||'_SUM) *100, 3) '
        'FROM XXBAXY.XXBAXY_BREAKDOWN_TAB '
        '   CROSS JOIN XXBAXY.XXBAXY_ATTR_SUM_TAB ' 
        'WHERE LOSS_CAT = ''Maintenance Related Losses''';

        EXECUTE IMMEDIATE sqlstr INTO m;
        EXECUTE IMMEDIATE 'INSERT INTO M_Maintenance (M_'||i||'_Maintenance) VALUES (:m)' USING m;
    END LOOP;
END;

答案 1 :(得分:0)

您的意思是,您的表格XXBAXY.XXBAXY_BREAKDOWN_TAB包含字段MONTH_1_COUNT,MONTH_2_COUNT,MONTH_3_COUNT等等吗?如果是这样,第一步应该是因为违反1NF而重新设计此表。这是糟糕的设计,一种不可改变的痛苦。如果不是,则不清楚为什么在没有任何字段引用的情况下尝试在SQL语句中使用未初始化的本地变量。

通常看起来你应该避免使用FOR LOOP和PL / SQL并编写一个insert / select语句来生成所有需要的行。

阐述:你的来源有一个共同的结构

begin
  for i in MIN..MAX loop
    select something into value 
      from table1 
      where some_condition 
      and id = i;
    insert into table2 values (value);
  end loop;
end;

几乎总是更好的方法就是这样做

insert into table2
  select something
  from table1
  where some_condition
  and id in (MIN..MAX);