代码之家  ›  专栏  ›  技术社区  ›  sam

当没有标识列时,如何进行批量插入?

  •  1
  • sam  · 技术社区  · 8 年前

    表有百万行,两列。

    code | name
    xyz  | product1
    abc  | Product 2
    ...
    ...
    

    我想通过insert into/select查询以小批量(10000)插入。

    当没有标识密钥来创建批次时,我们如何做到这一点?

    2 回复  |  直到 8 年前
        1
  •  2
  •   JNevill    8 年前

    您可以使用 LEFT OUTER JOIN 在您的 SELECT 语句来标识不在 INSERT 表,然后使用 TOP 获取数据库找到的第一个10000。类似于:

    INSERT INTO tableA
    SELECT TOP 10000 code, name
    FROM tableB LEFT OUTER JOIN tableA ON tableB.Code = tableA.Code
    WHERE tableA.Code IS NULL;
    

    然后一遍又一遍地跑,直到它吃饱为止。

    您还可以使用Windowing函数进行批处理,如:

    INSERT INTO tableA
    SELECT code, name
    FROM (
           SELECT code, name, ROW_NUMBER() OVER (ORDER BY name)  as rownum         
           FROM tableB
         )
    WHERE rownum BETWEEN 1 AND 100000;
    

    然后继续改变 BETWEEN 以获得您的批次。就我个人而言,如果我必须这样做,我会使用第一种方法,因为它可以保证捕获所有尚未存在的内容 TableA .

    此外,如果有可能 tableb 将在此批处理过程中获得记录,那么选项1肯定更好。本质上,使用option2,它将动态确定行数(),因此新插入的记录如果在批处理过程中出现,将导致丢失记录。

    如果 TableB 如果是静态的,那么选项2可能更快,因为DB只需对记录进行排序和编号,而不必将HUGE表连接到HUGE表格,然后抓取10000条记录。

        2
  •  0
  •   Dilip Nannaware    8 年前

    您可以在SELECT上进行分页,并按批次/页面大小(例如10000或任何您需要的大小)选择记录,然后将其插入目标表中。在下面的示例中,您必须更改所需批量大小的每次迭代的@Min和@Max值。

    INSERT INTO EmployeeNew
    SELECT Name
    FROM
    (
        SELECT DENSE_RANK OVER(ORDER BY EmployeeId) As Rank, Name
        FROM Employee
    ) AS RankedEmployee
    WHERE Rank >= @Min AND Rank < @Max