在oracle中执行批量插入的最佳方法是什么?

时间:2017-02-22 09:27:04

标签: oracle insert

有了这个,我的意思是在表格中插入数百万条记录。我知道如何使用循环插入数据,但是为了插入数百万的数据,它不是一个好方法。

我有两张桌子

CREATE TABLE test1
  (
    col1         NUMBER,
    valu         VARCHAR2(30),
    created_Date DATE,
    CONSTRAINT pk_test1 PRIMARY KEY (col1)
  )
/
CREATE TABLE test2
  (
    col2          NUMBER,
    fk_col1       NUMBER,
    valu          VARCHAR2(30),
    modified_Date DATE,
    CONSTRAINT pk_test2 PRIMARY KEY (col2),
    FOREIGN KEY (fk_col1) REFERENCES test1(col1)
  )
/

请建议一种方法,在没有循环的情况下插入一些高达100万的虚拟记录。

1 个答案:

答案 0 :(得分:2)

作为一种相当简单的方法,根据您的评论,您可能已经足够了,您可以使用a hierarchical query生成虚拟数据。在这里,我使用绑定变量来控制创建的数量,并使一些逻辑稍微清晰,但你可以使用文字。

首先,父行:

var parent_rows number;
var avg_children_per_parent number;
exec :parent_rows := 5;
exec :avg_children_per_parent := 3;

-- create dummy parent rows
insert into test1 (col1, valu, created_date)
select level,
  dbms_random.string('a', dbms_random.value(1, 30)),
  trunc(sysdate) - dbms_random.value(1, 365)
from dual
connect by level <= :parent_rows;

可能会生成如下行:

      COL1 VALU                           CREATED_DA
---------- ------------------------------ ----------
         1 rYzJBVI                        2016-11-14
         2 KmSWXfZJ                       2017-01-20
         3 dFSTvVsYrCqVm                  2016-07-19
         4 iaHNv                          2016-11-08
         5 AvAxDiWepPeONGNQYA             2017-01-20

然后是子行,在为父项生成的范围内随机fk_col1

-- create dummy child rows
insert into test2 (col2, fk_col1, valu, modified_date)
select level,
  round(dbms_random.value(1, :parent_rows)),
  dbms_random.string('a', dbms_random.value(1, 30)),
  trunc(sysdate) - dbms_random.value(1, 365)
from dual
connect by level <= :parent_rows * :avg_children_per_parent;

可能会产生:

select * from test2;

      COL2    FK_COL1 VALU                           MODIFIED_D
---------- ---------- ------------------------------ ----------
         1          2 AqRUtekaopFQdCWBSA             2016-06-30
         2          4 QEczvejfTrwFw                  2016-09-23
         3          4 heWMjFshkPZNyNWVQG             2017-02-19
         4          4 EYybXtlaFHkAYeknhCBTBMusGAkx   2016-03-18
         5          4 ZNdJBQxKKARlnExluZWkHMgoKY     2016-06-21
         6          3 meASktCpcuyi                   2016-10-01
         7          4 FKgmf                          2016-09-13
         8          3 JZhk                           2016-06-01
         9          2 VCcKdlLnchrjctJrMXNb           2016-05-01
        10          5 ddL                            2016-11-27
        11          4 wbX                            2016-04-20
        12          1 bTfa                           2016-06-11
        13          4 QP                             2016-08-25
        14          3 RgmIahPL                       2016-03-04
        15          2 vhinLUmwLwZjczYdrPbQvJxU       2016-12-05

每个父母的孩子数量各不相同:

select fk_col1, count(*) from test2 group by fk_col1 order by fk_col1;

   FK_COL1   COUNT(*)
---------- ----------
         1          1
         2          3
         3          3
         4          7
         5          1

要插入一百万行,只需更改绑定变量。

如果您需要孩子和父母之间更多的关系,例如所以修改日期总是在创建日期之后,可以修改查询;例如:

insert into test2 (col2, fk_col1, valu, modified_date)
select *
from (
select level,
  round(dbms_random.value(1, :parent_rows)) as fk_col1,
  dbms_random.string('a', dbms_random.value(1, 30)),
  trunc(sysdate) - dbms_random.value(1, 365) as modified_date
from dual
connect by level <= :parent_rows * :avg_children_per_parent
) t2
where not exists (
  select null from test1 t1
  where t1.col1 = t2.fk_col1 and t1.created_date > t2.modified_date
);

您可能还需要非午夜时间(我通过trunc()来电将所有内容设置为午夜,具体取决于列名称是&#39; date&#39; not&#39; datetime&#39;)或者某些列值为null;所以这可能只是你的起点。