Oracle SQL Loader有效地处理值中的内部双引号
我面临一些Oracle SQL Loader挑战,正在寻找一个高效简单的解决方案。 我要加载的源文件是以管道Oracle SQL Loader有效地处理值中的内部双引号,oracle,sql-loader,Oracle,Sql Loader,我面临一些Oracle SQL Loader挑战,正在寻找一个高效简单的解决方案。 我要加载的源文件是以管道|分隔的,其中的值用双引号括起来“。 问题似乎是某些值包含内部双引号 e、 g.:…“|”a:“b”|“… 这导致我的记录被拒绝,理由是: no terminator found after TERMINATED and ENCLOSED field 网络上有各种各样的解决方案,但似乎不适合: [1] 我尝试在引用引号时替换所有内部双引号, 但是,在控制文件的太多字段上应用此函数时 (我
|
分隔的,其中的值用双引号括起来“
。
问题似乎是某些值包含内部双引号
e、 g.:…“|”a:“b”|“…
这导致我的记录被拒绝,理由是:
no terminator found after TERMINATED and ENCLOSED field
网络上有各种各样的解决方案,但似乎不适合:
[1]
我尝试在引用引号时替换所有内部双引号,
但是,在控制文件的太多字段上应用此函数时
(我有大约2000多个字段,并且使用FILLER只加载一个子集)
装载机再次抱怨:
SQL*Loader-350: Syntax error at line 7.
Expecting "," or ")", found ",".
field1 char(36) "replace(:field1,'"','""')",
(我不知道为什么,但当将此解决方案应用于一小部分列时,它似乎确实有效)
问题是,所有字段都可能包含内部双引号
[2]
我可以在省略全局时加载所有数据(可选地由''
括起),但所有括起的引号都将成为目标表中数据的一部分
[3]
我可以省略由“”语句包围的全局,并将其仅放在选定的字段中,
虽然尝试在余数上替换(:field1,“,”)“
语句,但这很难实现,
因为我无法提前知道哪些可疑字段包含内部双引号
以下是我的问题:
如果封闭字段中没有管道,可以从控制文件中执行。不幸的是,如果在一个字段中同时包含管道和双引号,那么我认为您别无选择,只能对文件进行预处理 您的解决方案[1],即替换双引号,已经太晚了,没有用处;在执行SQL步骤之前,SQL*Loader已经解释了分隔符和附件。您的解决方案[2]忽略了封闭空间,将与[1]结合使用,直到其中一个字段包含管道字符。解决方案[3]与全局使用[1]和/或[2]存在相同的问题 该文件提到: 有时,作为分隔符的标点符号也必须包含在数据中。为了实现这一点,两个相邻的分隔符字符被解释为该字符的单个匹配项,并且该字符包含在数据中 换句话说,如果在字段中重复双引号,则它们将被转义并显示在表数据中。由于无法控制数据生成,因此可以预处理获得的文件,用转义双引号替换所有双引号。除非您不想全部替换它们,否则不应转义那些实际上是真实机柜的 您可以使用正则表达式将跳过其他字符的相关字符作为目标。这不是我的强项,但我想你可以用它来做 如果您有一个名为
orig.txt
的文件,其中包含:
"1"|A|"B"|"C|D"
"2"|A|"B"|"C"D"
3|A|""B""|"C|D"
4|A|"B"|"C"D|E"F"G|H""
你可以做:
perl -pe 's/(?<!^)(?<!\|)"(?!\|)(?!$)/""/g' orig.txt > new.txt
<>字段的开始和结束的双引号没有被修改,但是中间的两个引号现在被漏掉了。如果随后加载了带有双引号附件的控制文件:
load data
truncate
into table t42
fields terminated by '|' optionally enclosed by '"'
(
col1,
col2,
col3,
col4
)
然后你会得到:
select * from t42 order by col1;
COL1 COL2 COL3 COL4
---------- ---------- ---------- --------------------
1 A B C|D
2 A B C"D
3 A "B" C|D
3 A B C"D|E"F"G|H"
希望与您的原始数据相匹配。可能有一些边缘情况不起作用(例如字段中的双引号后跟管道),但您可以尝试解释其他人的数据的操作是有限的。。。当然,也可能有更好的正则表达式模式
<>您也可以考虑使用SQL*Load,如果数据文件是(或可以)在Oracle目录中,并且您有正确的权限。您仍然需要修改文件,但可以使用指令自动执行,而无需在调用SQL*Loader之前显式执行此操作。是否有任何封闭字段(可能包含或可能不包含双引号)包含分隔符管道字符?或者封闭框真的是多余的?是否可以在不使用附件的情况下生成源文件,或使用其他未使用的字符生成源文件?在处理之前删除它们可能并不困难(通过regex);但是,当前的
replace()
太晚了,这是在将记录拆分为字段之后。您也可以使用预处理器查看外部表以删除附件。在我处理的第一个文件中,数据中没有管道-我猜这在自由文本中是一个罕见的字符,但我不能假设它永远不会出现,我无法控制文件,字段可能包含第三方的自由文本。我知道我可能不得不去修复输入文件-我将不得不以一种简单有效的方式去做。我有点希望有一个简单的修复控制文件而不必每次处理数据本身(在加载程序之外)伟大的答案!这确实澄清了我对这个问题的选择
select * from t42 order by col1;
COL1 COL2 COL3 COL4
---------- ---------- ---------- --------------------
1 A B C|D
2 A B C"D
3 A "B" C|D
3 A B C"D|E"F"G|H"