从xml插入多个记录

时间:2014-08-06 21:39:22

标签: postgresql xpath

我希望批量插入到PostgreSQL数据库中:后端代码会创建类似

的XML
<items>
   <i dt="2014-08-01" name="vvv" count="12" />
   <i dt="2014-08-02" name="zzz" count="6" />
</items>

我想传递给一个函数并一次性保存所有值。

但是我坚持xpath:每个“列”似乎是一个值数组,我不知道如何将它们插入到表中。这是一个测试示例:

CREATE TEMP TABLE temp_values (dt date, name varchar, count int);

WITH x AS (SELECT '
  <items>
    <i dt="2014-08-01" name="vvv" count="12" />
    <i dt="2014-08-02" name="zzz" count="6" />
    <i dt="2014-08-03" name="bbd" count="10" />
  </items>'::xml AS t
)
INSERT INTO temp_values
SELECT 
  xpath('/items/i/@dt', t),
  xpath('/items/i/@name', t),
  xpath('/items/i/@count', t)
FROM  x;

现在,最后我希望temp_values有3条记录,就像在XML中一样,但是表格是空的。

如果您注释掉“insert into”行,您会看到值已正确解析。它只是返回一个记录,其中每列是一个数组,而不是返回多个记录。

我错过了什么?

2 个答案:

答案 0 :(得分:0)

好的,显然unnest和数组索引是解决方案:

  

不要(数组)|将数组扩展为一组行

所以代码是

CREATE TEMP TABLE temp_values (dt date, name varchar, count int) ON COMMIT DROP;

WITH x AS (SELECT '
  <items>
    <i dt="2014-08-01" name="vvv" count="12" />
    <i dt="2014-08-02" name="zzz" count="6" />
    <i dt="2014-08-03" name="bbd" count="10" />
  </items>'::xml AS t
)
INSERT INTO temp_values
SELECT 
  CAST(CAST((xpath('//@dt', node))[1] as varchar) as date),
  CAST((xpath('//@name', node))[1] as varchar),
  CAST(CAST((xpath('//@count', node))[1] as varchar) as int)
FROM (SELECT unnest(xpath('/items/i', t)) AS node FROM x) sub;

SELECT * FROM temp_values

答案 1 :(得分:0)

我更喜欢在@:

之前删除一些额外的斜杠
CREATE TEMP TABLE temp_values (dt date, name varchar, count int) ON COMMIT DROP;

WITH x AS (SELECT '
  <items>
    <i dt="2014-08-01" name="vvv" count="12" />
    <i dt="2014-08-02" name="zzz" count="6" />
    <i dt="2014-08-03" name="bbd" count="10" />
  </items>'::xml AS t
)
INSERT INTO temp_values
SELECT 
  CAST(CAST((xpath('@dt', node))[1] as varchar) as date),
  CAST((xpath('@name', node))[1] as varchar),
  CAST(CAST((xpath('@count', node))[1] as varchar) as int)
FROM (SELECT unnest(xpath('/items/i', t)) AS node FROM x) sub;

SELECT * FROM temp_values