TLDR版本: 批量插入将告诉您它受影响的行数。它不会告诉你TRIED要影响的行数,或者失败的行数。这个问题直观明显,我想知道是否有更可靠的方法从文本文件上传,将代码保存在服务器内。
完整版:我有一个应用程序需要定期将文本数据文件上传到SQL Server表中。出于一些疯狂和疯狂的原因,我想把它放在一个存储过程中,使其成为抽象层的一部分,而不是让前端应用程序直接写入表。
与大多数SQL Server脚本一样,我花费了大量的时间来抨击砖墙以使其完全正常工作。 (在本网站和其他网站上搜索过去的帖子时,可以获得少量帮助。)
批量插入是否会读取标题行以确定要写入哪些字段?不,我必须使用格式文件(并希望表结构/顺序永远不会更改)或使用仅包含数据文件中的列的临时表。登台表在将数据复制到真实表之前接收数据。
如果省略目标表中的单个列(即使是具有默认值的列)并且不使用格式文件,该怎么办?你得到了如此自我解释的错误消息“无法从OLE DB提供程序获取行”BULK“对于链接服务器”(null)“。”使用上述登台表,省略任何不在数据源中的列,可以解决这个问题。
没关系,我可以忍受。这不是可怕的部分。这是。
如果登台表仍有任何定义为NOT NULL的字段,但该列的数据源行为null,则不会出现错误。根据我的测试,如果你有(比方说)5行数据而行3在NOT NULL字段中缺少数据,那么你将不会收到错误但会收到消息“4行更新”。如果您期望5行并且对受影响的行数进行交叉检查以确保预期的数量存在,那么这一切都很好并且很花哨,但这些文件的长度会有所不同而且Bulk Insert不会告诉您它实际读取了多少行。更糟糕的是,在某些情况下,一行中缺少的字段也会阻止上传(有效)行。
明显的解决方案?从登台表中删除NOT NULL约束,并处理登台表和实际表之间的接口中的任何空异常。但是......我担心的是,这件事可能会在我尚未遇到的其他情况下做同样的事情。也就是说,读取一行,无法将其写入登台表,并且不会抛出异常,以便在找到它之前没有人知道数据丢失,并发现它不存在。甚至Access也有比这更好的文本导入选项。
我的问题是,是否有一种更好(更可靠)的方法来处理向SQL Server上传可变行长文本文件而无需依赖前端应用程序来执行此操作?
提前感谢任何建议。
答案 0 :(得分:1)
.NET SqlBulkCopy
可以在将数据传输到临时表时为您提供更多控制,并且仍能提供出色的性能。
现在,考虑到你想要服务器本身的所有逻辑,也许以下策略可能适合你:
保持登台表没有任何可能导致您的流程失败的限制。在其上创建了其他列,例如IsValid
和ErrorMessage
列。
然后编写一个存储过程,验证每行的数据,检查条件,缺失值,文本长度,以及您可能要强制执行的任何自定义业务规则。
每个验证可以是登台表的单个UPDATE
语句,设置IsValid
或ErrorCode
加ErrorMessage
,条件为{{1}例如,
一旦运行了所有验证WHERE
语句,您应该有一个对导入有效的行子集(标记为IsValid的行)和其他可以清楚地识别问题原因并记录或通知的行用户逐行。
在经常导入无效数据的情况下,该策略证明非常有效。
现在,如果您要并行运行多个导入进程,那么您可能需要根据某个“进程标识符”将导入的数据划分到临时表中并可能将其编入索引,以避免在进程之间锁定对数据运行批量验证。
答案 1 :(得分:0)
System.Data.Client中的SqlBulkCopy类应该为您提供更多控制和反馈。
答案 2 :(得分:0)
即使处理不规则的文件仍然很困难,我仍然会使用SSIS。它为您提供了很多控制和良好的性能。