在 SQL 中向父子 table 批量插入操作
Bulk insert operation into Parent and Child table in SQL
对于我们当前的项目 (.Net Core),我们需要迁移旧数据,其中数据为 excel sheet 格式的纯文本。我们需要导入数据,然后将这些数据创建到我们的数据库中。此迁移涉及多个 table。假设 table 是:
table Parent(
Id UNIQUEIDENTIFIER PRIMARY KEY,
Name varchar(120),
value varchar(150)
)
table Child1(
Id UNIQUEIDENTIFIER PRIMARY KEY,
childvalue1 varchar(120),
childvalue2 varchar(150),
P_ID UNIQUEIDENTIFIER foreign_key # has an index
)
table Child2(
Id UNIQUEIDENTIFIER PRIMARY KEY,
child2value1 varchar(200),
P_ID UNIQUEIDENTIFIER foreign_key # has an index
)
关系是:Parent有一对多的Child1,Child2.
父 table 引用了 table A.
数据在 excel sheet 中的格式是:
Name - value - childvalue1 - childvalue2 - child2value1
这种格式有数千行。
我想做的是:
- 将excel数据复制到table
- 创建一个存储过程以插入到父项和子项中 tables
我关心的是:
- 如何在逐行上传数据时将父id映射到子id?
- 在插入条目时也必须生成 Id,并且 id 是 GUID 类型
对于从 Excel file
到 database
的 bulk insert
,如果您想要一个高性能的应用程序,请遵循此方法。
首先,创建一个 temp table
对应于您的 Excel 文件列和一个名为 InsertionKey
.
的多列
使用相同的 InsertionKey(生成新的 GUID)从 excel 插入所有输入数据,并且所有 Excel 行都将具有相同的键。 (使用 Entity Framework BulkInsertAsync
或 SqlBulkCopy
进行批量插入。您还可以查看我的 GitHub 存储库以在 .Net 中对 BulkInsert 进行基准测试)
插入数据后,将GUID
作为参数发送给存储过程
现在,您可以使用密钥从临时 table 中提取数据,从而轻松处理所有插入的数据。
示例:
您的 excel 文件列:
Item1 Red 25
Item2 Black 32
Item3 Orange 44
在批量插入之前生成一个新的 Guid
var insertionKey = Guid.NewGuid();
现在批量插入数据库:
Item1 Red 25 insertionKey
Item2 Black 32 insertionKey
Item3 Orange 44 insertionKey
现在用 Insertionkey
调用存储过程
YourStoredProcedure(Insertionkey)
存储过程内部:
select *
into #temp
from temptable
where insertionKey = insertionKeyParameter
在这里您可以读取插入的行,然后根据需要对其进行处理。
这里有一个示例脚本,它提供了有关如何执行此操作的概念。它依赖于值的唯一性,即给定的 name/value 只有一个含义
首先,您需要将 excel 数据加载到舞台 table。
然后您可以使用 T-SQL 将这些值分配给三个 table。通过重新加入值,您可以检索父 ID 的
注意这里没有循环,这是一个基于集合的解决方案。
DECLARE @Parent TABLE (
Id UNIQUEIDENTIFIER PRIMARY KEY DEFAULT newsequentialid() NOT NULL,
Name varchar(120),
value varchar(150)
)
DECLARE @Child1 TABLE(
Id UNIQUEIDENTIFIER PRIMARY KEY DEFAULT newsequentialid() NOT NULL,
childvalue1 varchar(120),
childvalue2 varchar(150),
P_ID UNIQUEIDENTIFIER
)
DECLARE @Child2 TABLE (
Id UNIQUEIDENTIFIER PRIMARY KEY DEFAULT newsequentialid() NOT NULL,
child2value1 varchar(200),
P_ID UNIQUEIDENTIFIER
)
-- This is the stage table that excel data is loaded into
DECLARE @Stage TABLE (
COL1 VARCHAR(100),
COL2 VARCHAR(100),
COL3 VARCHAR(100),
COL4 VARCHAR(100),
COL5 VARCHAR(100)
)
-- Load sample data
INSERT INTO @Stage(COL1,COL2,COL3,COL4,COL5)
VALUES
('Name1','value1','childvalue1','childvalue2','child2value1'),
('Name1','value1','childvalue3','childvalue4','child4value1'),
('Name1','value1','childvalue3','childvalue4','child4value2'),
('Name1','value1','childvalue3','childvalue4','child4value3'),
('Name2','value2','childvalue8','childvalue5','child5value1'),
('Name2','value2','childvalue8','childvalue6','child6value1'),
('Name2','value2','childvalue8','childvalue6','child6value2')
-- Save top level, generating id's
INSERT INTO @Parent(Name,Value)
SELECT DISTINCT COL1,COL2 FROM @Stage
-- save children, looking up id's based on actual values
INSERT INTO @Child1(P_ID,childvalue1,childvalue2)
SELECT DISTINCT P.Id, S.COL3,S.COL4
FROM @Stage S
INNER JOIN @Parent P
-- relies on these values being unique
ON S.COL1 = P.Name
AND S.COL2 = P.value
-- Check results
SELECT * FROM @Parent
SELECT * FROM @Child1
对于我们当前的项目 (.Net Core),我们需要迁移旧数据,其中数据为 excel sheet 格式的纯文本。我们需要导入数据,然后将这些数据创建到我们的数据库中。此迁移涉及多个 table。假设 table 是:
table Parent(
Id UNIQUEIDENTIFIER PRIMARY KEY,
Name varchar(120),
value varchar(150)
)
table Child1(
Id UNIQUEIDENTIFIER PRIMARY KEY,
childvalue1 varchar(120),
childvalue2 varchar(150),
P_ID UNIQUEIDENTIFIER foreign_key # has an index
)
table Child2(
Id UNIQUEIDENTIFIER PRIMARY KEY,
child2value1 varchar(200),
P_ID UNIQUEIDENTIFIER foreign_key # has an index
)
关系是:Parent有一对多的Child1,Child2.
父 table 引用了 table A.
数据在 excel sheet 中的格式是:
Name - value - childvalue1 - childvalue2 - child2value1
这种格式有数千行。
我想做的是:
- 将excel数据复制到table
- 创建一个存储过程以插入到父项和子项中 tables
我关心的是:
- 如何在逐行上传数据时将父id映射到子id?
- 在插入条目时也必须生成 Id,并且 id 是 GUID 类型
对于从 Excel file
到 database
的 bulk insert
,如果您想要一个高性能的应用程序,请遵循此方法。
首先,创建一个
的多列temp table
对应于您的 Excel 文件列和一个名为InsertionKey
.使用相同的 InsertionKey(生成新的 GUID)从 excel 插入所有输入数据,并且所有 Excel 行都将具有相同的键。 (使用 Entity Framework
BulkInsertAsync
或SqlBulkCopy
进行批量插入。您还可以查看我的 GitHub 存储库以在 .Net 中对 BulkInsert 进行基准测试)插入数据后,将
GUID
作为参数发送给存储过程
现在,您可以使用密钥从临时 table 中提取数据,从而轻松处理所有插入的数据。
示例:
您的 excel 文件列:
Item1 Red 25
Item2 Black 32
Item3 Orange 44
在批量插入之前生成一个新的 Guid
var insertionKey = Guid.NewGuid();
现在批量插入数据库:
Item1 Red 25 insertionKey
Item2 Black 32 insertionKey
Item3 Orange 44 insertionKey
现在用 Insertionkey
YourStoredProcedure(Insertionkey)
存储过程内部:
select *
into #temp
from temptable
where insertionKey = insertionKeyParameter
在这里您可以读取插入的行,然后根据需要对其进行处理。
这里有一个示例脚本,它提供了有关如何执行此操作的概念。它依赖于值的唯一性,即给定的 name/value 只有一个含义
首先,您需要将 excel 数据加载到舞台 table。
然后您可以使用 T-SQL 将这些值分配给三个 table。通过重新加入值,您可以检索父 ID 的
注意这里没有循环,这是一个基于集合的解决方案。
DECLARE @Parent TABLE (
Id UNIQUEIDENTIFIER PRIMARY KEY DEFAULT newsequentialid() NOT NULL,
Name varchar(120),
value varchar(150)
)
DECLARE @Child1 TABLE(
Id UNIQUEIDENTIFIER PRIMARY KEY DEFAULT newsequentialid() NOT NULL,
childvalue1 varchar(120),
childvalue2 varchar(150),
P_ID UNIQUEIDENTIFIER
)
DECLARE @Child2 TABLE (
Id UNIQUEIDENTIFIER PRIMARY KEY DEFAULT newsequentialid() NOT NULL,
child2value1 varchar(200),
P_ID UNIQUEIDENTIFIER
)
-- This is the stage table that excel data is loaded into
DECLARE @Stage TABLE (
COL1 VARCHAR(100),
COL2 VARCHAR(100),
COL3 VARCHAR(100),
COL4 VARCHAR(100),
COL5 VARCHAR(100)
)
-- Load sample data
INSERT INTO @Stage(COL1,COL2,COL3,COL4,COL5)
VALUES
('Name1','value1','childvalue1','childvalue2','child2value1'),
('Name1','value1','childvalue3','childvalue4','child4value1'),
('Name1','value1','childvalue3','childvalue4','child4value2'),
('Name1','value1','childvalue3','childvalue4','child4value3'),
('Name2','value2','childvalue8','childvalue5','child5value1'),
('Name2','value2','childvalue8','childvalue6','child6value1'),
('Name2','value2','childvalue8','childvalue6','child6value2')
-- Save top level, generating id's
INSERT INTO @Parent(Name,Value)
SELECT DISTINCT COL1,COL2 FROM @Stage
-- save children, looking up id's based on actual values
INSERT INTO @Child1(P_ID,childvalue1,childvalue2)
SELECT DISTINCT P.Id, S.COL3,S.COL4
FROM @Stage S
INNER JOIN @Parent P
-- relies on these values being unique
ON S.COL1 = P.Name
AND S.COL2 = P.value
-- Check results
SELECT * FROM @Parent
SELECT * FROM @Child1