我创建了一个管道和两个链接服务,将数据从SQL Server的预处理实例移动到Azure SQL实例。我遇到的问题是,我们的on-prem中有一个表"table-1",其Identity(1,1)列缺少序列ID(例如,值为1、2、3、4、6)。当管道运行时,它试图插入ID为1、2、3、4、5的行,这是一个大问题,因为ID 6是另一个表"table-2"上的外键,现在它不存在,所以将数据移动到table-2失败,并出现SQL错误547(insert语句与外键约束冲突…)
在我看来,正确的做法是让该列不是一个身份,但这对我来说不是一个选择,因为创建记录的应用程序代码希望该列是自动生成的。
除了不使用数据工厂之外,还有什么办法可以解决这个问题吗?我希望看到它能自动为带有identity列的表打开和关闭identity_insert,虽然我知道这会迫使这些表一次处理一个,但这个选项很好,不会破坏我的关系。
编辑:根据wBob的建议,我还在这里添加了一个功能请求(如果你愿意投票的话):https://feedback.azure.com/forums/270578-data-factory/suggestions/17996950-add-support-for-maintaining-identity-column-values
Azure数据工厂本机不支持打开或关闭表的标识属性,但想到了两种解决方案。
- 使用数据工厂将数据加载到临时表中(其中未设置标识属性),然后使用存储过程任务调用存储过程,在该存储过程中可以进行更严格的控制,包括打开或关闭标识属性
- 如果您使用的是Azure SQL数据库(或虚拟机上的SQL Server),则可以使用表值参数,并通过这种方式将数据传递到存储过程任务中,跳过临时表。此技术不适用于Azure SQL数据仓库。我可能不会推荐这种高音量。此示例显示了如何:
https://github.com/Microsoft/azure-docs/blob/master/includes/data-factory-sql-invoke-stored-procedure.md
我还没能测试这些,但相信它们会起作用。如果你有任何问题,请告诉我。
我接受了wBob的回答,但想在我所做的事情中加入更多的细节。
我可能有100个表要移动,其中包含各种依赖关系和标识。以下是我将数据导入azure的步骤:
-
创建一个管道来移动通过查询sys.tables:找到的所有没有标识和依赖项的表
select * from sys.tables t where not exists ( select * from sys.columns c where c.object_id = t.object_id and is_identity = 1 )
并将这里的结果与oType=8的CCD_ 1的结果进行比较。然后,我取了这个结果集中oSequence=1(没有依赖项)的所有表,并将这些表放在管道中运行
-
我创建了一个临时架构,并重新创建了所有具有标识列的表(通过删除(1.)中查询中的"not"找到,其中有60多个),并在创建这些表时删除了标识规范。
-
然后,我创建了另一个数据工厂管道,将数据移动到这些暂存表中。
-
运行了一堆"插入…"语句将数据从暂存表移动到承载标识的对应表中,每次都设置identity_insert打开和关闭。注意:在这里,我还必须注意sp_msdependencies的结果,以免出现外部错误
-
创建了一个数据工厂管道来移动其余的表。
Whew。。。
今天遇到了这个问题,有一个2500万行的数据集,所以真的想做一个Ident Insert,而不是通过另一个表暂存。
在复制数据(接收/预复制脚本)步骤中,只需添加:设置identity_insert[schema]。上的[表]
在以下位置之后立即添加查找:设置identity_insert[schema]。[桌子]关选择1作为结果集
你需要结果,因为这是一个查找,别忘了,你一次只能运行其中一个步骤,因为Ident insert一次只能在一个表上,除非有人告诉我SQL 2005:-)