使用LOOP和SELECT进行INSERT

时间:2012-12-18 13:37:44

标签: oracle plsql oracle11g

我正在尝试使用INSERT / SELECT组合从其他表插入数据。我还需要通过特定计算插入增量。但是,我无法弄清楚它为什么不起作用。

我有这样的表(temp_business_area):

 ----------
 | bname  |
 ----------
 | London |
 | Sydney |
 | Kiev   |
 ----------

我想在枚举表中有这个:

 -----------------------------------------------------------------
 | identifier    | language_id |   code | data   | company_limit |
 ----------------------------------------------------------------|
 | BUSINESS_UNIT |    0        |   100  | London | 126           |
 | BUSINESS_UNIT |    0        |   200  | Sydney | 126           |
 | BUSINESS_UNIT |    0        |   300  | Kiev   | 126           |
 -----------------------------------------------------------------

但我得到的是:

-----------------------------------------------------------------
 | identifier    | language_id |   code | data   | company_limit |
 ----------------------------------------------------------------|
 | BUSINESS_UNIT |    0        |   100  | London | 126           |
 | BUSINESS_UNIT |    0        |   100  | Sydney | 126           |
 | BUSINESS_UNIT |    0        |   100  | Kiev   | 126           |
 | BUSINESS_UNIT |    0        |   200  | London | 126           |
 | BUSINESS_UNIT |    0        |   200  | Sydney | 126           |
 | BUSINESS_UNIT |    0        |   200  | Kiev   | 126           |
 | BUSINESS_UNIT |    0        |   300  | London | 126           |
 | BUSINESS_UNIT |    0        |   300  | Sydney | 126           |
 | BUSINESS_UNIT |    0        |   300  | Kiev   | 126           |
 -----------------------------------------------------------------

这是我的循环。

BEGIN 
    FOR x IN 1 .. 3 LOOP
         INSERT INTO enum (identifier, language_id, code, data, company_limit)
         SELECT 'BUSINESS_UNIT', 0, x*100, bname, 126 FROM temp_business_area;
    END LOOP;
END;

我无法弄清楚我在哪里弄错了。帮助

2 个答案:

答案 0 :(得分:10)

您正在为temp_business_area中的每个行执行三次插入,这就是您最终获得9行的原因。

根据您想要实现的描述,您根本不需要循环。

只需使用一个插页:

INSERT INTO enum (identifier, language_id, code, data, company_limit)
SELECT 'BUSINESS_UNIT', 
        0,  
        row_number() over (order by null) * 100, 
        bname, 126 
FROM temp_business_area;

SELECT语句将返回3行,每行将插入enum表中。 row_number()函数将返回每行(1,2,3)的递增值,乘以100将生成所需的代码。

修改
(在David的评论之后):

使用窗口函数确实会给语句增加一些开销。如果不需要对编号进行额外控制,则使用ROWNUM会更有效(尽管只有三行无关紧要)。

INSERT INTO enum (identifier, language_id, code, data, company_limit)
SELECT 'BUSINESS_UNIT', 
        0,  
        rownum * 100, 
        bname, 126 
FROM temp_business_area;

答案 1 :(得分:7)

您可以使用其他两种变体:

declare

i integer := 1;

BEGIN 

    FOR x IN (select distinct bname from temp_business_area) LOOP

         INSERT INTO enum (identifier, language_id, code, data, company_limit)
         SELECT 'BUSINESS_UNIT', 0, i*100, x.bname, 126 FROM temp_business_area;

         i := i + 1;

    END LOOP;
END;

变体2

BEGIN 

        FOR x IN 1..3 LOOP

             INSERT INTO enum (identifier, language_id, code, data, company_limit)
             SELECT distinct 'BUSINESS_UNIT', 0, x*100, bname, 126 FROM temp_business_area WHERE rownum = x;


        END LOOP;
    END;