当行依赖外键值时如何使用BULK INSERT?

时间:2011-12-05 03:09:31

标签: tsql memory foreign-keys bulkinsert

我的问题与this one I asked on ServerFault有关。

基于此,我考虑过使用BULK INSERT。我现在明白,我必须为每个要保存到数据库中的实体准备一个文件。无论如何,我仍然想知道这个BULK INSERT是否会避免我的系统上的内存问题,如ServerFault上引用的问题所述。

至于Streets表,它很简单!我只有两个城市和五个部门需要关心作为外键。但那么,地址怎么样? Addresses表的结构如下:

AddressId int not null identity(1,1) primary key
StreetNumber int null
NumberSuffix_Value int not null DEFAULT 0
StreetId int null references Streets (StreetId)
CityId int not null references Cities (CityId)
SectorId int null references Sectors (SectorId)

正如我在ServerFault上所说,我有大约35,000个要插入的地址。我要记住所有的ID吗? = P

然后,我现在让公民人员插入与地址有联系的人。

PersonId int not null indentity(1,1) primary key
Surname nvarchar not null
FirstName nvarchar not null
IsActive bit
AddressId int null references Addresses (AddressId)

我唯一能想到的就是强制ID为静态值,但是,我失去了以前使用INSERT..SELECT状态的方法所带来的灵活性。

那么我的选择是什么?

  1. 我强制ID始终相同,然后我必须SET IDENTITY_INSERT ON以便我可以强制将值放入表中,这样我的每个行总是有相同的ID正如建议here

  2. 如何使用外键进行BULK INSERT?我无法在任何地方获得任何文档。 =(

  3. 感谢您的帮助!

      

    修改

         

    我进行了编辑,以便包含最终为我制作的BULK INSERT SQL指令!

    我的Excel工作簿准备好了我需要插入的信息。因此,我只是创建了一些补充工作表并开始编写公式,以便将信息数据“导入”到这些新工作表中。我的每个实体都有一个。

    1. 街道;
    2. 地址;
    3. 公民。
    4. 至于其他两个实体,不值得批量插入它们,因为我只有两个城市和五个扇区(城市细分)要插入。插入城市和部门后,我注意到各自的ID,并开始准备我的批量插入记录集。顺便说一句,利用Excel的强大功能来计算值并“导入”外键本身就是一种魅力。之后,我将每个工作表保存为单独的CSV文件。然后我的记录就准备好了。

      USE [DatabaseName]
      GO
      
      delete from Citizens
      delete from Addresses
      delete from Streets
      
      BULK INSERT Streets
          FROM N'C:\SomeFolder\SomeSubfolder\Streets.csv'
          WITH (
              FIRSTROW = 2
              , KEEPIDENTITY
              , FIELDTERMINATOR = N','
              , ROWTERMINATOR = N'\n'
              , CODEPAGE = N'ACP'
          )
      GO
      
        
          
      • FIRSTROW

             

        表示开始插入的行号。在我的情况下,我的CSV包含列标题,因此第二行是开头的那一行。除此之外,人们可能想要从他的档案中的任何地方开始,比方说第15行。

      •   
      • KEEPIDENTITY

             

        即使表具有标识列,也允许批量插入指定的文件内实体ID。当您希望插入精确ID时,此参数与插入行之前的SET INDENTITY_INSERT my_table ON相同。

      •   

      至于其他参数,他们自己说话。

      现在解释了这一点,为剩下的两个实体中的每一个重复相同的代码以插入地址和公民。并且因为指定了KEEPIDENTITY,所以我的所有外键都保持不变,尽管我的主键在SQL Server中设置为标识。

      虽然只有一些调整,就像marc_s在答案中所说的那样,只需尽可能快地将数据导入到一个没有任何限制的临时表中。通过这种方式,你可以让你的生活更轻松,同时遵循良好的做法。 =)

1 个答案:

答案 0 :(得分:16)

基本思路是将您的数据批量插入暂存表,该表没有任何限制,任何约束等。 - 只需尽可能快地批量加载数据。

在登台表中有数据后,然后,当您将登台表中的数据插入真实表格时,您需要开始担心约束等。

在这里,你可以这样。

  • 仅将这些行插入符合所有条件的实际工作表中(并在临时表中将其标记为“已成功插入”)

  • 处理临时表中未被某些错误/恢复过程成功插入的所有行 - 无论是什么:打印包含所有“问题”行的报告,将它们扔进“错误bin“或其他 - 完全取决于你。

关键点是:实际的BULK INSERT应该进入一个完全无约束的表 - 只需尽可能快地加载数据 - 然后在第二步开始担心约束和查找数据和引用这样的东西