【发布时间】:2015-05-23 05:08:28
【问题描述】:
输入文件在同一行中最多有 34 种不同的记录类型。
文件用竖线分隔,每个记录类型用“~”分隔(原始记录类型除外。
并非每行都包含所有 34 种记录类型,我也不需要全部。
所有记录类型都将按指定顺序发送,但并非所有记录类型都将始终发送。第一个记录类型是强制性的,将始终发送。在 34 种类型中,只有 7 种是强制性的。
每种记录类型都有预定义的字段数量,如果在客户和我们的负载之间没有适当的提前期,则绝不应偏离该定义。
将根据所需的记录类型使用所有所需的列来构造 Oracle 表。因此,一行将包含来自与输入文件类似的每种记录类型的信息,但还会包含来自某些未包含在输入中的记录类型的列的空值。
我正在寻找的最终结果是一种对输入文件执行条件格式化以生成输出的方法,该输出可以通过 sqlldr 简单地加载到 shell 脚本中,而不是通过 PL/SQL(如我所愿我的非 PL/SQL 同事能够解决/修复加载过程中遇到的任何问题)。
有 3 条记录的小例子(在这个例子中数据类型无关紧要):
Record Types: AA, BB, CC, DD, EE, FF
AA has 5 fields (Mandatory)
BB has 2 fields (Optional)
CC has 3 fields (Optional)
DD has 6 fields (Optional)
EE has 4 fields (Optional)
FF has 2 fields (Not needed. Skipping in output)
GG has 4 fields (Optional)
AA|12345|ABCDE|67890|FGHIJ|~BB|12345|~CC|ABCDE|12345|~DD|A|B|C|D|E|~EE|1|2|3|~FF|P|~GG|F|R|T
AA|23456|BCDEF|78901|GHIJK|~CC|BCDEF|23456|~EE|2|3|4|~GG|R|F|G
AA|34567|CDEFG|89012|HIJKL|~DD|B|C|D||~FF|Q
第 1 行没有问题,因为它包含所有可用的记录类型,但第 2 行和第 3 行没有。因此需要修改它们以包含缺失的记录类型。整体输出需要如下所示:
AA|12345|ABCDE|67890|FGHIJ|~BB|12345|~CC|ABCDE|12345|~DD|A|B|C|D|E|~EE|1|2|3|~GG|F|R|T
AA|23456|BCDEF|78901|GHIJK|~BB||~CC|BCDEF|23456|~DD||||||~EE|2|3|4|~GG|R|F|G
AA|34567|CDEFG|89012|HIJKL|~BB||~CC|||~DD|B|C|D||~EE||||~GG|||
我已经开始获取每条记录,将其拆分为自己的文件,然后使用:
typeset -i count=0
while read record
do
newfile="`echo $file`.$count.dat"
echo $record | sed 's/|~/\n/g' > $newfile
count=$count+1
done < $file
将每个记录类型放在所述文件中自己的行中,但是将其回滚到包含所有可能字段的一行中是非常棘手的。这显然不是最好的方法,因为每个文件可以有几千条记录,这将导致几千个文件,但我以此为起点来降低逻辑。
有什么想法吗?
【问题讨论】:
-
听起来像是一个可怕的组织。你确定你不会对 N 个文件做得更好吗,每个记录类型一个?
-
每个记录类型的某个地方是否有文档信息,需要多少个字段,以及它们出现的顺序?或者字段集可以按任何顺序排列,因此您可以在一行中按该顺序排列~EE、~DD、~CC、~BB、~AA?脚本如何知道应该存在哪些记录?如果遇到不应该存在的记录应该怎么办(示例中的 ~FF 有 5 种记录类型)?如果一切都已排序,如果检测到乱序数据该怎么办?
-
请使用额外信息更新问题(然后删除这些 cmets)。还有两个问题:(1)如果~AA 应该总是有5 个字段,如果遇到只有4 个字段的记录,或者~AA 有6 个字段会发生什么? (2) 是否存在一种将始终存在的记录类型,或者它们都是可选的?
-
问题已更新。
-
感谢您更新问题。这是正常的做法——这个问题需要尽可能地独立,因为 cmets 名义上是“瞬态的”;它们可以被删除,但问题应该继续易于理解和回答。
标签: unix awk grep sql-loader