我的问题与我在ServerFault上提出的问题有关。
基于此,我考虑使用BULK INSERT
。我现在明白了,我必须为要保存到数据库中的每个实体准备一个文件。但无论如何,我仍然想知道这个BULK INSERT是否会避免我系统上所描述的内存问题,就像在ServerFault上引用的问题一样。
至于Streets表,它非常简单!我只需要关心两个城市和五个区域作为外键。但是,地址表怎么办?地址表的结构如下:
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”策略所拥有的任何灵活性。
那么我的选择是什么?
- 我强制将ID始终设置为相同的值,然后我必须使用
SET IDENTITY_INSERT ON
来强制将值插入表中,这样每行的ID都是相同的,正如此处所建议的那样。 - 如何使用外键进行批量插入?我无法在任何地方找到相关文档。=(
编辑:
我编辑了以包含
BULK INSERT
SQL指令,最终成功了!我已经准备好要插入的Excel工作簿信息。所以,我只需创建一些辅助工作表,并开始编写公式,以便将信息数据“导入”到这些新工作表中。我为我的每个实体都创建了一个工作表:
- 街道;
- 地址;
- 公民。
至于另外两个实体,它们不值得批量插入,因为我只有两个城市和五个部门(城市细分)需要插入。一旦城市和部门都插入完成,我就记录了它们各自的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,即使表中有自增列。这个参数与在插入行时使用
SET INDENTITY_INSERT my_table ON
来精确插入ID是相同的。
至于其他参数,它们本身就很清楚了。
现在这个代码对于剩下的两个实体——地址和公民——进行了重复。由于指定了KEEPIDENTITY
,所有的外键都保持不变,尽管我的主键在SQL Server中被设置为自增列。
只需要做一些微调,就像marc_s
在他的回答中所说的那样,尽可能快地将数据导入到一个没有任何限制的临时表中。这样,你会更轻松地完成任务,同时仍然遵循良好的实践。=)
KEEPIDENTITY
,因此可以在CSV文件中指定外键值,并期望插入这些外键值。 - Will Marcouiller