MySQL有一个很好的声明:LOAD XML LOCAL INFILE
例如,如果您有此表:
CREATE TABLE person (
person_id INT NOT NULL PRIMARY KEY,
fname VARCHAR(40) NULL,
lname VARCHAR(40) NULL
);
Run Code Online (Sandbox Code Playgroud)
以及名为person.xml的以下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>
Run Code Online (Sandbox Code Playgroud)
你可以这样做:
LOAD XML LOCAL INFILE 'person.xml'
INTO TABLE person
ROWS IDENTIFIED BY '<person>';
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果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>
Run Code Online (Sandbox Code Playgroud)
如何在不操作XML文件的情况下使用MySQL语句完成相同的操作?我到处搜索但找不到答案.
Bil*_*win 10
XML文件中与物理列名称不对应的字段将被忽略.表中没有XML中相应字段的列设置为NULL.
我要做的是加载到临时表中,如@Kolink建议的那样,但是还有其他列.SET从XML加载数据时添加子句.
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 |
+-----------+--------+-------------+-----------+-------------+----------+
Run Code Online (Sandbox Code Playgroud)
然后复制到真实表,选择列的子集.
INSERT INTO person SELECT person_id, fname, lname FROM person_xml;
Run Code Online (Sandbox Code Playgroud)
或者,删除额外的列并使用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 |
+-----------+--------+-------------+
Run Code Online (Sandbox Code Playgroud)
以下是我可以使用的选项:
选项 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。它工作完美而且速度超级快。
| 归档时间: |
|
| 查看次数: |
12213 次 |
| 最近记录: |