【问题标题】:Can SSIS import TXT records in exact same order as they are in TXT file? If not (by default), then how?SSIS 可以按照与 TXT 文件中完全相同的顺序导入 TXT 记录吗?如果不是(默认情况下),那怎么办?
【发布时间】:2018-10-17 22:48:05
【问题描述】:

我有一个平面文件中的记录,其中包含您可能认为是主记录的内容,其中详细记录在它们相关的主记录之后,直到主记录。

这是一个例子:

Order123, Customer1, 1/1/2018
Item1, $1
Item2, $1
Order124, Customer2, 1/1/2018
Item1, $1
Item4, $2

该文件没有内置的行号或任何类型的排序,也没有使用外键将主与细节相关联。

如果我要使用 SSIS 将原始 TXT 数据导入一个灵活的表中,该表的列旨在采用各种数据类型(即 nvarchar(255) 或类似的),我可以在导入后迭代这些值,并将第 2 行和第 3 行中带有 Order123 的值;因此,第 5 行和第 6 行是 Order124。

保存原始数据的表将使用一个简单的 RecordID 标识列,其中整数递增一。

这并不重要,但如果你好奇的话,我所指的实际数据是 Retrosheet 数据事件文件。它是所有美国职业棒球大联盟数据的集合。可以从此页面上的链接下载真实文件: https://www.retrosheet.org/game.htm

我似乎记得您无法将 TXT 数据导入表并期望行的顺序与 TXT 行的顺序相匹配。但是,当我对此进行小型测试时,记录确实以与源文件相同的顺序出现。我怀疑我的小测试结果好得令人难以置信,也不能预测结果如何。

总结:

如何使用 SSIS 导入数据,按照与原始平面文件相同的顺序插入 SQL 记录?

【问题讨论】:

  • 回想一下,是否是 DTS(SSIS 之前的数据转换服务)中的“多阶段数据泵”使原始数据无序?也许这就是我质疑这个的原因?
  • 我试图确认这一点,但我认为它们确实是按顺序出现的。即使如此,如果没有对数据进行排序的方法,您将无法按顺序查询/处理它们。您需要在表格上有类似 IDENTITY 列的内容。
  • 源将以其自然顺序被消耗。但在那之后,不能保证它会保持这种状态。当数据进入时,您可能需要分配一个行号,如果您必须再次对其进行排序,则随后使用该行号。您可以通过脚本组件(转换)任务直接提供源,该任务每次处理一行时都会计数,并将该计数器分配给新的输出列。
  • 实际上没有 GTD... 学到了这个艰难的方式。我最终加载为 single_blob,然后用序列号解析
  • 脚本组件添加行号是要走的路。只有几行 C# 或 vb

标签: sql-server ssis data-warehouse


【解决方案1】:

答案是肯定的,只要您不应用任何类型的排序,平面文件就会按顺序处理。

我能够通过在我的数据库中创建一个表来处理 Retrosheet 文件,该表具有一个标识列和一个足够长的 varchar 列以容纳文件的每一行(我选择了 100)。然后我使用Ragged Right 格式设置我的平面文件连接,将行分隔符定义为{CR}{LF}

【讨论】:

  • 您能否提供任何说明平面文件按顺序处理的参考资料。感谢您的帮助。
  • @digital-aaron - 我目前有一个 ETL 包,可以读取 CSV 文件并根据前 2 行执行特定任务。它具有推送到 OLEDB 目标数据库表的平面文件源。表有 IDENTITY 列。请参阅此 link 关于 12 百万行的文本文件。另一个link 使用脚本任务添加行ID。
【解决方案2】:

我刚刚输入了这个,所以可能有一些语法错误,但它应该让你接近。

您需要设置 2 个不同的输出。

加载顺序无关紧要,因为您要向详细信息表添加外键。

public string orderNo; /// on the OUTSIDE

public main()



string[] lines = System.IO.File.ReadAllLines([filename]);

foreach(var line in lines)
{
   string[] cols = line.Split(',');
   if(cols.Length == 3)
   {
      orderNo = cols[0];
      Output0Buffer.AddRow();
      Output0Buffer.OrderNo = cols[0].ToString();
      Output0Buffer.Customer = cols[1].ToString();
      Output0Buffer.OrderDate = DateTime.Parse(cols[2].ToString().Trim());
   }
   else
   {
      Output1Buffer.AddRow();
      Output1Buffer.OrderNo = orderNo;
      Output1Buffer.Item = cols[0].ToString();
      Output1Buffer.Amt = cols[1].ToString(); //This needs to be parsed later.
   }
}

跟进:

我刚刚查看了您尝试下载的网站。而且该文件比您提出的问题要复杂。

Split 似乎仍然可以安全使用,但您必须修剪一些引号包裹的字符串(名称),但看起来没有引号包裹的逗号(至少在示例中)。如果是这种情况,则需要使用 REGEX 进行拆分。

我将更改逻辑以使用 switch 和 case 并将其基于 cols[0] 作为 8 种类型之一。

将 ID 保存在外部,并写入为链接到父级而创建的其他 7 个可能的数据集中的每一个。对于需要绑定到不同父级的其他记录,您必须使用相同的策略(我认为评论就是一个例子)。

祝你一切顺利。剧本看起来并不容易解读!

【讨论】:

  • 我忘记了一件大事。我忘了斯普利特!我修复了代码,它现在应该可以工作了。
  • 这看起来是一个有趣的项目。你打算如何处理这些数据?
猜你喜欢
  • 2014-04-25
  • 2023-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-12
  • 2022-11-26
  • 2018-12-03
相关资源
最近更新 更多