使用 scope_identity 多插入如何?
Posted
技术标签:
【中文标题】使用 scope_identity 多插入如何?【英文标题】:Multi insert with scope_identity how to? 【发布时间】:2019-04-08 13:22:39 【问题描述】:我对 SSIS OLE DB 命令有疑问。
我要做的是插入“person”表并从插入中获取新创建的PersonID
(表标识),因为我需要它来创建与 PersonContactInfo 表的关系,这应该是很简单。
我无法编写存储过程,并且大约有 10k 行,因此使用 OLE DB 命令应该没问题。
我已尝试编写此代码,它应该匹配:
DECLARE @PersonID int
---
--- create new person
---
INSERT INTO [dbo].[Personer_LF_TEST] (Fornavne, Efternavne, Oprindelse, OprettetDato, OprettetAf,OprindelseID)
VALUES (?, ?, 'Klimaquiz', ?, 499,7)
SET @PersonID = (SELECT SCOPE_IDENTITY())
---
--- update phonenumber
---
INSERT INTO [dbo].[Kontaktinfo_LF_TEST](PersonID, KontaktInfoTypeID, Notat, Tekst, Oprettet)
VALUES (@PersonID, 5, ?,?, Getdate() )
---
--- update Email
---
INSERT INTO [dbo].[Kontaktinfo_LF_TEST](PersonID, KontaktInfoTypeID, Notat, Tekst, Oprettet)
VALUES (@PersonID, 2,?, ?, Getdate() )
---
--- create persontypecode
---
INSERT INTO [dbo].[PersonArtskoder_LF_TEST](PersonID, ArtskoderID, Notat, Aktiv, CreatedBy, CreatedOn, ModifiedBy, ModifiedOn, StartDato, SlutDato)
VALUES (@PersonID,?, ?, 1, 209, getdate(), 209, getdate(), getdate(), NULL )
我也尝试过像这样成功运行第一部分:
-- Create new Person
INSERT INTO [dbo].[Personer_LF_TEST](Fornavne, Efternavne, Oprindelse, OprettetDato, OprettetAf, OprindelseID)
VALUES (?, ?,'Klimaquiz',?,499,7)
插入 10k 行
如果尝试这样做,它会失败
-- Create new person
INSERT INTO [dbo].[Personer_LF_TEST](Fornavne, Efternavne, Oprindelse, OprettetDato, OprettetAf, OprindelseID)
VALUES(?, ?, 'Klimaquiz', ?, 499, 7)
-- Insert Phone number
INSERT INTO [dbo].[Kontaktinfo_LF_TEST](PersonID, KontaktInfoTypeID, Tekst, Oprettet)
VALUES (1, 5, ?, Getdate())
错误是:
数据流任务 [OLE DB 命令 [178]] 出错:SSIS 错误代码 dts_E_OLEDBERROR。发生了 OLE DB 错误。
错误代码:0x80004005。 OLE DB 记录可用。来源: ” Microsoft SQL Server Native Client 11.0" Hresult:0x80004005 说明:“插入值列表与列列表不匹配”
但输入应与列列表匹配。
这是我希望 OLD DB 命令执行的“有点”代码
DECLARE @PersonID int
---
--- create new person
---
INSERT INTO [dbo].[Personer_LF_TEST](Fornavne, Efternavne, Oprindelse, OprettetDato, OprettetAf,OprindelseID)
VALUES ('Simster', 'Mann', 'Klimaquiz', '03-25-2019', 499,7)
SET @PersonID = (SELECT scope_identity())
---
--- update phonenumber
---
INSERT INTO [dbo].[Kontaktinfo_LF_TEST](PersonID, KontaktInfoTypeID, Notat, Tekst, Oprettet)
VALUES (@PersonID, 5, 'WEB','22004400', Getdate() )
---
--- update Email
---
INSERT INTO [dbo].[Kontaktinfo_LF_TEST](PersonID, KontaktInfoTypeID, Notat, Tekst, Oprettet)
VALUES (@PersonID, 2,'WEB', 'Simster@codewithme.dk', Getdate() )
---
--- create persontypecode
---
INSERT INTO [dbo].[PersonArtskoder_LF_TEST](PersonID, ArtskoderID, Notat, Aktiv, CreatedBy, CreatedOn, ModifiedBy, ModifiedOn, StartDato, SlutDato)
VALUES (@PersonID,'30395', 'WEB', 1, 209, getdate(), 209, getdate(), getdate(), NULL )
【问题讨论】:
如果我在 SSMS 中使用虚拟数据执行此查询,我执行它没有问题 【参考方案1】:如果我在 SSMS 中使用虚拟数据执行此查询,我执行它没有问题,
DECLARE @PersonID int
---
--- create new person
---
INSERT INTO [dbo].[Personer_LF_TEST](Fornavne, Efternavne, Oprindelse, OprettetDato, OprettetAf,OprindelseID)
VALUES ('TEST', 'Simmy', 'Klimaquiz', GETDATE(), 499,7)
SET @PersonID = (SELECT scope_identity())
---
--- update phonenumber
---
INSERT INTO [dbo].[Kontaktinfo_LF_TEST](PersonID, KontaktInfoTypeID, Notat, Tekst, Oprettet)
VALUES (@PersonID, 5, 'WEB',33445566, Getdate() )
---
--- update Email
---
INSERT INTO [dbo].[Kontaktinfo_LF_TEST](PersonID, KontaktInfoTypeID, Notat, Tekst, Oprettet)
VALUES (@PersonID, 2,'WEB', 'simster@codewithme.dk', Getdate() )
---
--- create persontypecode
---
INSERT INTO [dbo].[PersonArtskoder_LF_TEST](PersonID, ArtskoderID, Notat, Aktiv, CreatedBy, CreatedOn, ModifiedBy, ModifiedOn, StartDato, SlutDato)
VALUES (@PersonID,'30895', 'WEB', 1, 209, getdate(), 209, getdate(), getdate(), NULL )
我成功插入了 4 行,但我无法让它在 OLE DB 命令对象中工作。我的想法是在流中添加一列,然后在数据流之后添加一个执行 sql 命令,然后执行 SQL 命令将基于列中的输入插入、更新或删除/不执行任何操作。但这似乎是一种乏味的方式。
【讨论】:
这是问题的附录吗? 您已将此作为答案发布。这是否意味着您的问题已解决? 您可以使用新信息修改您的原始帖子(最好标记为编辑或更新)。我建议您这样做,然后删除此答案。【参考方案2】:我认为最好的方法可能是将其分解。
使用此链接 http://radacad.com/output-parameter-of-stored-procedure-in-ole-db-command-ssis 添加编辑以处理此问题是 SSIS:
-
将您的数据读入数据流。
1.1(编辑)添加派生列并将 ID 设置为 null(dt_int)
-
使用 OLE DB 命令插入新行并将范围标识返回到列中。
2.1(编辑)将您的列映射到返回 scope_identity() 的存储过程的输出参数
-
使用多播并为派生列设置 3 个新路径
使用派生列输入硬编码值
使用 OLEDB Destination 一次性插入所有记录。
这允许您批量插入 3 个后续查询。
后期编辑:
就像我说的,我对 C# 脚本组件很快,这是一个如何做到这一点的示例......
how to get the last record number after inserting record to database in access
【讨论】:
谢谢 KeithL,你有关于如何让 OLE DB 将 ID 返回到列中的链接吗?我看过这个***.com/questions/8914818/… ......但是他们把它放在这里在 SSIS 变量中,但这对我不起作用... :-S 我不得不承认。我会很快跳到 c#,但这看起来是如何使用 SSIS 的一个很好的例子。 radacad.com/… 但是如果不能创建存储过程呢?那么您的解决方案将不起作用? :-( 添加了如何在 C# 脚本组件中执行步骤 2 的链接以上是关于使用 scope_identity 多插入如何?的主要内容,如果未能解决你的问题,请参考以下文章
如果使用多个插入语句,有啥方法可以使用 SCOPE_IDENTITY 吗?
SCOPE_IDENTITY,多个插入,如果当前插入没有插入,则携带前一个插入的值