2011-12-20 96 views
7

MySQL有一個不錯的語句:LOAD XML LOCAL INFILELOAD XML LOCAL INFILE

舉例來說,如果你有這樣的表:

CREATE TABLE person (
    person_id INT NOT NULL PRIMARY KEY, 
    fname VARCHAR(40) NULL, 
    lname VARCHAR(40) NULL 
); 

和被叫下面的XML文件person.xml :

<list> 
     <person> 
      <person_id>1</person_id> 
      <fname>Mikael</fname> 
      <lname>Ronström</lname> 
     </person> 
     <person> 
      <person_id>2</person_id> 
      <fname>Lars</fname> 
      <lname>Thalmann</lname> 
     </person> 
</list> 

你可以這樣做:

LOAD XML LOCAL INFILE 'person.xml' 
INTO TABLE person 
ROWS IDENTIFIED BY '<person>'; 

我的問題是,如果XML文件中的列名與表中的不同,該怎麼辦?例如:

<list> 
     <person> 
      <PersonId>1</PersonId> 
      <FirstName>Mikael</FirstName> 
      <LastName>Ronström</LastName> 
     </person> 
     <person> 
      <PersonId>2</PersonId> 
      <FirstName>Lars</FirstName> 
      <LastName>Thalmann</LastName> 
     </person> 
</list> 

如何在不操縱XML文件的情況下用MySQL語句完成相同的操作?我到處搜索,但無法找到答案。

回答

4

下面分別提供給我的選項:

選項1:創建具有不同的字段名稱的臨時表(由其他答案的建議)。這將是一個令人滿意的方法。但是,當我嘗試它時,出現了一個新問題:出於某種原因,LOAD XML語句不接受最小化格式的空元素(例如<person />)。所以,這個語句失敗了,因爲我偶爾需要加載的XML文件有這種格式的空元素。

選項2:在運行LOAD XML語句以更改元素名稱並修改空元素格式之前,使用XSLT轉換XML文件。這是不可行的,因爲XML文件非常大,並且XSLT處理引擎在處理之前將整個XML加載到內存中。

選項3:完全繞過LOAD XML語句,並使用SAX解析器來解析XML文件,並使用JDBC和預準備語句將記錄直接插入到數據庫中。儘管原始的JDBC和準備好的語句通常是有效的,但事實證明這太慢了。比LOAD XML語句慢得多。

選項4:使用LOAD DATA語句代替LOAD XML語句,並使用與該語句相關的可選子句來適應我的需要(例如,由等分隔的行)。這可能已經奏效,但會容易出錯並且不穩定。

選項5:使用快速只進解析器解析文件並同時讀取/寫入XML元素,並生成一個新的XML文件,其中所需格式的修改名稱爲LOAD XML語句。

我最終使用了選項5.我使用Java Streaming API for XML(StAX)來讀取XML文件並生成修改後的XML文件,然後通過JDBC從Web應用程序內部運行LOAD XML LOCAL INFILE。它工作完美,速度超快。

2

您可以使用XML文件中的列名創建臨時表(儘管這需要在create temporary table查詢中手動完成),請將XML文件加載到該表中,然後將insert into person select * from tmp_table_name加載到該表中。

+0

這是一個非常好的工作。但是,正如我對Bill Karwin的回答評論的那樣,LOAD XML語句存在另一個問題。它不接受最小化的空標籤,如。你能想出解決這個問題的辦法嗎? – stepanian 2011-12-27 19:05:29

+0

我從來沒有使用過'LOAD XML',所以我只是對這個答案進行了有根據的猜測。所以不,不幸的是,我不知道這個問題的解決方案,除了以另一種語言(例如PHP)加載XML文件,解析它,然後將結果查詢發送到數據庫。 – 2011-12-27 19:10:40

+1

僅供參考如果未能加載標記是一個錯誤,並且已經修復:在MySQL 5.5.46之前,LOAD XML沒有正確處理形式的空XML元素。 (錯誤#67542,錯誤#16171518)_。從[這裏](https://dev.mysql.com/doc/refman/5.5/en/load-xml.html) – radman 2017-05-08 05:50:25

10

不符合物理列名稱的XML文件中的字段將被忽略。並且表中XML中沒有對應字段的列被設置爲NULL。

我會做的是加載到一個臨時表,因爲@Kolink建議,但有額外的列。從XML加載數據時添加SET子句。

CREATE TEMP TABLE person_xml LIKE person; 

ALTER TABLE person_xml 
    ADD COLUMN FirstName VARCHAR(40), 
    ADD COLUMN LastName VARCHAR(40), 
    ADD COLUMN PersonId INT; 

LOAD XML LOCAL INFILE 'person.xml' INTO TABLE person_xml 
    SET person_id = PersonId, fname = FirstName, lname = LastName; 

SELECT * FROM person_xml; 
+-----------+--------+-------------+-----------+-------------+----------+ 
| person_id | fname | lname  | FirstName | LastName | PersonId | 
+-----------+--------+-------------+-----------+-------------+----------+ 
|   1 | Mikael | Ronström | Mikael | Ronström |  1 | 
|   2 | Lars | Thalmann | Lars  | Thalmann |  2 | 
+-----------+--------+-------------+-----------+-------------+----------+ 

然後複製到真正的表,選擇列的子集。

INSERT INTO person SELECT person_id, fname, lname FROM person_xml; 

或者,刪除多餘的列並使用SELECT *

ALTER TABLE person_xml 
    DROP COLUMN PersonId, 
    DROP COLUMN FirstName, 
    DROP COLUMN LastName; 

INSERT INTO person SELECT * FROM person_xml; 

SELECT * FROM person; 

+-----------+--------+-------------+ 
| person_id | fname | lname  | 
+-----------+--------+-------------+ 
|   1 | Mikael | Ronström | 
|   2 | Lars | Thalmann | 
+-----------+--------+-------------+ 
+0

謝謝。出現了一個新問題。顯然,這個聲明不喜歡這樣的空元素。它需要單獨的打開和關閉標籤。我不確定是否有解決辦法。 – stepanian 2011-12-24 04:06:37

+0

我想說你應該學習XSLT。 – 2011-12-24 04:20:52

+0

XSLT將如何幫助您? – stepanian 2011-12-24 04:33:44

4

一點點哈克,但工作液使用好老LOAD DATA INFILE

LOAD DATA LOCAL INFILE '/tmp/xml/loaded.xml' 
INTO TABLE person 
CHARACTER SET binary 
LINES STARTING BY '<person>' TERMINATED BY '</person>' 
(@person) 
SET 
    person_id = ExtractValue(@person:=CONVERT(@person using utf8), 'PersonId'), 
    fname = ExtractValue(@person, 'FirstName'), 
    lname = ExtractValue(@person, 'LastName') 
; 

附:如果數據包含逗號,則可能需要另外使用字段分隔符進行播放。

+0

這可能容易出錯。太hacky。儘管感謝您的回答。 – stepanian 2011-12-27 19:02:06

+0

謝謝。 'LOAD XML'的速度優勢是一個數量級 – myol 2016-05-16 14:40:37

0

MySQL表架構:organization_type(ID,姓名)

organizationtype.xml:

<NewDataSet> 
    <row> 
     <ItemID>1</ItemID> 
     <ItemCreatedBy>53</ItemCreatedBy> 
     <ItemCreatedWhen>2014-03-10T22:53:43.947+10:00</ItemCreatedWhen> 
     <ItemModifiedBy>53</ItemModifiedBy> 
     <ItemModifiedWhen>2014-03-10T22:53:43.99+10:00</ItemModifiedWhen> 
     <ItemOrder>1</ItemOrder> 
     <ItemGUID>e2ad051f-b7ea-4feb-b91e-f558f6f632a0</ItemGUID> 
     <Name>Company Type 1</Name> 
    </row> 

和MySQL進口查詢將是這樣的:

LOAD XML INFILE '/var/lib/mysql-files/organizationtype.xml' 
INTO TABLE organization_type (@ItemID, @Name) 
SET [email protected], [email protected] 
相關問題