使用不一致的列名称加载XML LOCAL INFILE

ste*_*ian 7 xml mysql

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)


ste*_*ian 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。它工作完美而且速度超级快。