我有一个文件,每行有四个字段,如下所示:
<uri> <uri> <uri> <uri> .
:_non-spaced-alphanumeric <uri> "25"^^<uri:integer> <uri> .
:_non-spaced-alphanumeric <uri> "Hello"@en <uri> .
:_non-spaced-alphanumeric <uri> "just text in quotes" <uri> .
...
和这个sql脚本:
LOAD DATA LOCAL INFILE 'data-0.nq'
IGNORE
INTO TABLE btc.btc_2012
FIELDS
TERMINATED BY ' ' OPTIONALLY ENCLOSED BY '"'
LINES
TERMINATED BY '.\n'
(subject,predicate,object,provenance);
示例中的第三个字段可以是上面列出的任何格式。我并不关心第三个值,除非它是一个uri,无论如何都被脚本解析得很好。但如果不是那么第四个字段由引用后的第三个字段加上第四个字段组成。
有没有一种方法可以让它在不操纵文件的情况下工作,顺便说一下是17GB?
答案 0 :(得分:0)
是的,有一种方法可以解决这个问题。将数据字段加载到MySQL用户变量中,然后将表达式分配给实际列。
例如,代替:
(subject,predicate,object,provenance
做这样的事情:
(subject, predicate, @field3, @field4)
SET object = CASE WHEN @field3 LIKE '"%"_%' THEN ... ELSE @field3 END
, provenance = CONCAT(CASE WHEN @field3 LIKE '"%"%_"' THEN ... ELSE '' END,@field4)
那只是一个大纲。显然,那些...
需要替换为适当的表达式,这些表达式返回您想要分配给列的字段值的部分。 (这将是SUBSTRING,SUBSTRING_INDEX,INSTR,LOCATE,REPLACE等字符串函数的某种组合,您可能需要额外的WHEN结构来处理变体。
(我不清楚你需要检查什么条件。)
如果这是在Unix或Linux上运行,另一种选择是使用命名管道,外部程序读取文件,执行require操作,并写入命名管道,在后台运行。
e.g。
> mkfifo /tmp/mydata.pipe
> myprogram <myfile >/tmp/mydata.pipe 2>/tmp/mydata.err &
mysql> LOAD DATA LOCAL INFILE /tmp/mydata.pipe ...
<强>后续强>
使用这样的输入行:
abc def "Hello"@en klm .
给出FIELDS TERMINATED BY ' ' OPTIONALLY ENCLOSED BY '"'
field1 = 'abc'
field2 = 'def'
field3 = '"Hello"@en'
field4 = 'klm'
要测试field3包含双引号的情况,并将第一个双引号作为字符串中的第一个字符,我们可以使用以下内容:
LIKE '"%"%'
这表示第一个字符必须是双引号,后跟零个或多个字符,后跟另一个双引号,再跟零一个或多个字符。
在第二个双引号之前获取field3的部分:
SUBSTRING_INDEX(@field3,'"',2)
要摆脱那个引用的双引号,即返回field3中双引号之间的内容,你可以这样做:
SUBSTRING_INDEX(SUBSTRING_INDEX(@field3,'"',2),'"',-1)
要获得最后双引号后面的field3部分:
SUBSTRING_INDEX(SUBSTRING_INDEX(@field3,'"',-1)
(这些表达式假设field3中最多有两个双引号。)
获取第三列的值:
CASE
-- when field starts with a double quote and is followed by another double quote
WHEN @field3 LIKE '"%"%"'
-- return whats between the double quotes in field3
THEN SUBSTRING_INDEX(SUBSTRING_INDEX(@field3,'"',2),'"',-1)
-- otherwise return the entirety of field3
ELSE @field3
END
要获取要添加到第四列的值,当field3包含两个双引号时:
CASE
-- when field starts with a double quote and is followed by another double quote
WHEN @field3 LIKE '"%"%"'
-- return whats after the last double quote in field3
THEN SUBSTRING_INDEX(@field3,'"',-1)
-- otherwise return an empty string
ELSE ''
END
要将其添加到field4,请使用上面带有te CASE表达式的CONCAT
函数和field4。
这些是我们期望插入表中的值:
column1 = 'abc'
column2 = 'def'
column3 = 'Hello'
column4 = '@enklm'
另一个关注
如果LOAD DATA没有识别行分隔符,因为它没有识别字段分隔符,那么你必须抛弃字段分隔符,并自己进行解析。将整行加载到用户变量中,然后解析。
e.g。
LINES TERMINATED BY '.\n'
(@line)
SET subject
= SUBSTRING_INDEX(@line,' ',1)
, predicate
= SUBSTRING_INDEX(SUBSTRING_INDEX(@line,' ',2),' ',-1)
, object
= CASE
WHEN SUBSTRING_INDEX(SUBSTRING_INDEX(@line,' ',3),' ',-1) LIKE '"%'
THEN SUBSTRING_INDEX(SUBSTRING_INDEX(@line,'"',2),'"',-1)
ELSE SUBSTRING_INDEX(SUBSTRING_INDEX(@line,' ',3),' ',-1)
END
, provenance
= CASE
WHEN SUBSTRING_INDEX(SUBSTRING_INDEX(@line,' ',3),' ',-1) LIKE '"%'
THEN SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(@line,'"',-1),' ',2),' ',-1)
ELSE SUBSTRING_INDEX(SUBSTRING_INDEX(@line,' ',4),' ',-1)
END
这将适用于示例数据中的所有行,其中的字段由单个空格分隔,但第三个字段中的双引号匹配除外。
注意:SQL中可用于字符串操作的函数会导致语法笨拙和笨拙; SQL并不是专为简单的字符串操作而设计的。