Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle SQL Loader有效地处理值中的内部双引号_Oracle_Sql Loader - Fatal编程技术网

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] 我尝试在引用引号时替换所有内部双引号, 但是,在控制文件的太多字段上应用此函数时 (我

我面临一些Oracle SQL Loader挑战,正在寻找一个高效简单的解决方案。 我要加载的源文件是以管道
|
分隔的,其中的值用双引号括起来
。 问题似乎是某些值包含内部双引号

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,“,”)“
语句,但这很难实现, 因为我无法提前知道哪些可疑字段包含内部双引号

以下是我的问题:

  • 有没有简单的方法可以说服加载器小心处理内部双引号(当值包含在双引号中时)

  • 如果我被迫修复数据缓存,是否有一个单行Linux命令只将内部双引号转换为另一个字符串/字符, 比如说,单引号

  • 如果我被迫将带引号的数据加载到目标表中,是否有一种简单的方法可以从所有字段中删除封闭的双引号, 一次完成所有操作(表中约有1000列)。对于非常大的表,解决方案是否具有实用性能


  • 如果封闭字段中没有管道,可以从控制文件中执行。不幸的是,如果在一个字段中同时包含管道和双引号,那么我认为您别无选择,只能对文件进行预处理

    您的解决方案[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"