0

TLDR 版本:批量插入将告诉您它影响了多少行。它不会告诉你它试图影响多少行,或者有多少行失败。这个问题很明显,我想知道是否有更可靠的方式从文本文件上传,将代码保存在服务器中。

完整版:我有一个应用程序需要定期将文本数据文件上传到 SQL Server 表中。出于某种疯狂和疯狂的原因,我想把它放在一个存储过程中,使其成为抽象层的一部分,而不是让前端应用程序直接写入表。

与大多数 SQL Server 脚本一样,我通常会花费大量时间将头撞在砖墙上以使其完全正常工作。(通过搜索本网站和其他网站上的过去帖子获得了不小的帮助。)

批量插入是否会读取标题行以确定要写入哪些字段?不,我必须使用格式文件(并希望表结构/顺序永远不会改变)或使用仅包含数据文件中的列的临时表。暂存表在将数据复制到实际表之前接收数据。

如果您省略了目标表中的单个列(即使是具有默认值的列)并且不使用格式文件怎么办?您会收到不言自明的错误消息“无法从链接服务器“(null)”的 OLE DB 提供程序“BULK”中获取一行。” 使用上述临时表,省略任何不在数据源中的列,可以解决这个问题。

没关系,我可以忍受。这不是可怕的部分。这是。

如果暂存表仍有任何定义为 NOT NULL 的字段,但该列的数据源行为 null,则不会出现错误。根据我的测试,如果您有(比如说)5 行数据并且第 3 行在 NOT NULL 字段中缺少数据,那么您不会收到错误消息,但会收到“4 行已更新”消息。如果您期望 5 行并交叉检查受影响的行数以确保存在预期的行数,这一切都很好,但这些文件的长度会有所不同,批量插入不会告诉您它实际读取了多少行。更糟糕的是,在某些情况下,一行中缺少的字段也会阻止下一个(有效)行的上传。

明显的解决方案?从暂存表中删除 NOT NULL 约束并处理暂存表和真实表之间的接口中的任何空异常。但是...我担心的是,在我还没有遇到的其他情况下,这段 cro...ode 可能会做同样的事情。也就是说,读取一行,未能将其写入暂存表,并且不抛出异常,因此没有人知道数据丢失,直到他们去寻找它并发现它不存在。甚至 Access 也有比这更好的文本导入选项。

那么,我的问题是......是否有更好(更可靠)的方式来处理将可变行长度文本文件上传到 SQL Server 而不必依赖前端应用程序来完成它?

提前感谢您的任何建议。

4

3 回答 3

1

.NETSqlBulkCopy将在将数据传输到临时表时为您提供更多控制,并且仍然提供出色的性能。

现在,考虑到您想要服务器本身的所有逻辑,也许以下策略可能对您有用:

保持暂存表没有任何可能使您的流程失败的限制。在其上创建其他列,例如IsValid, 加一ErrorMessage列。

然后编写一个存储过程来验证每一行的数据,检查条件、缺失值、文本长度以及您可能想要强制执行的任何自定义业务规则。

例如,每个验证都可以是登台表的单个UPDATE语句,设置IsValidErrorCode加号ErrorMessage,在其WHERE子句上具有条件。

运行所有验证UPDATE语句后,您应该有一个对导入有效的行子集(标记为 IsValid 的行)和其他行,您可以在这些行上清楚地确定问题的原因并逐行记录或通知用户.

在频繁导入无效数据的情况下,该策略被证明是非常有效的。

现在,如果您要并行运行多个导入进程,那么您可能需要根据一些“进程标识符”划分暂存表中的导入数据并可能对其进行索引,以避免在运行质量时在进程之间锁定对数据的验证。

于 2012-06-20T23:16:16.120 回答
0

System.Data.Client 中的SqlBulkCopy类应该为您提供更多控制和反馈。

于 2012-06-20T22:47:13.227 回答
0

即使处理不完整的文件仍然很困难,我仍然会为此使用 SSIS。它为您提供了很多控制和良好的性能。

于 2012-06-20T23:52:36.823 回答