2014-05-12 22 views
0

我有每行四個字段,看起來像這樣的文件:MySQL的LOAD DATA INFILE非洽場

<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); 

第三字段中示例可以是以上所見的任何格式。我真的不關心的3個值,除非它是一個URI,這是由腳本解析罰款反正。但是,如果不是,則第四個字段由引用後的第三部分加上第四個本身組成。

有沒有方法可以讓我得到它的工作,而不處理文件,它的方式是17GB?

+0

答案已經處理了你正在做的任何事情,我只是建議您在嘗試將數據帶入數據庫之前先考慮其他方式來清理/規範化數據。有幾個ETL工具(有些是免費的!),可以幫助這個 – Noah

回答

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運行,另一個選擇是使用一個命名管道和外部程序讀取該文件,執行需要的操作,並寫入命名管,在後臺運行。

例如

> 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包含雙引號,與作爲f的第一個雙引號在字符串中IRST字符,我們可以用這樣的:

LIKE '"%"%' 

,說的第一個字符是一個雙引號,後面的零個一個或多個字符,緊接着又雙引號,由零隨後再次一個或多個字符。

到了第二個雙引號之前拿到場3部分:

SUBSTRING_INDEX(@field3,'"',2) 

爲了擺脫從領先的雙引號,即返回場3雙引號之間有什麼,你能做些什麼像這樣:

SUBSTRING_INDEX(SUBSTRING_INDEX(@field3,'"',2),'"',-1) 

要獲得繼上雙引號中的字段3部分:

SUBSTRING_INDEX(SUBSTRING_INDEX(@field3,'"',-1) 

(這些表達式假設有在字段3至多兩個雙引號)。

要針對第三列獲得的價值:

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中,使用CONCAT功能用TE CASE表達上述和field4中。

而這些都是我們所期待已插入到表中的值:如果LOAD DATA是不承認的行分隔符,因爲

column1 = 'abc' 
column2 = 'def' 
column3 = 'Hello' 
column4 = '@enklm' 

ANOTHER隨訪

它不會識別字段分隔符,那麼您必須放棄字段分隔符,並自己進行解析。將整行加載到用戶變量中,並解析。

例如

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不是專門爲簡單的字符串操作而設計的。

+0

再次看看SQL腳本,它似乎不工作,因爲我期望。 ''''這個語句'FIELDS TERMINATED BY'''''''''''''''絕對不會終止':'非空格字母數字「你好」@。'我相信這是因爲第二個'''是預計會在這種情況下發生一個空白。因此,我不確定是否有任何解決方法。有什麼想法嗎? –

+0

@Valentino Hudhra:我希望'field3'不會被一個空格(指定的字段終止符)後面的「引用」引用。這就是爲什麼我的示例表達式中的CASE表達式正在尋找第三場內的雙引號模式。你的問題表明,想解析第三個領域的報價之間的內容,並將其分配到第三欄;並且在第二個雙引號之後(在第三個字段中)並且將其與第四個字段連接,以分配給第四個列。 – spencer7593

+0

是的,確切地說。但field3不會被「引用」(結尾),因此,文件的其餘部分(或者與TEXT SQL字段可以包含的一樣多)存儲在field3中。因此,您無法真正使用CASE做很多事情,因爲您是缺少行... –