【发布时间】:2018-05-01 19:20:10
【问题描述】:
PostgreSQL 版本 9.6,使用 xml2 扩展。我正在尝试从 XML 中提取行并将它们插入到 postgreSQL 表中。这是一个简短的例子:
ROLLBACK;
BEGIN;
DO $$
DECLARE
v_xml xml;
v_record RECORD;
BEGIN
v_xml := '<?xml version="1.0" encoding="UTF-16"?>
<root>
<table>
<row><a>1</a><b>2</b><c>3</c></row>
<row><a></a><b>5</b><c>6</c></row>
<row><a>7</a><b>8</b><c>9</c></row>
</table>
</root>'::text;
CREATE TEMPORARY TABLE temptable( col_a text, col_b text, col_c text ) ON COMMIT DROP;
INSERT INTO temptable VALUES
(
unnest(xpath('/root/table/row/a/text()', v_xml))::text,
unnest(xpath('/root/table/row/b/text()', v_xml))::text,
unnest(xpath('/root/table/row/c/text()', v_xml))::text
);
-- display table contents
FOR v_record IN SELECT * FROM temptable LOOP
RAISE NOTICE 'col_a: % col_b: % col_c: %', v_record.col_a, v_record.col_b, v_record.col_c;
END LOOP;
END $$;
当没有值为 NULL 时,这可以正常工作:
NOTICE: col_a: 1 col_b: 2 col_c: 3
NOTICE: col_a: 4 col_b: 5 col_c: 6
NOTICE: col_a: 7 col_b: 8 col_c: 9
但是,对于缺失值或 NULL 值,unnest() 无法正确识别它们并使用其列数组的下一个值(应该为 next 行读取。
为了演示,修改 XML 如下(即将前 4 和 9 值设为 null,或完全删除元素):
<table>
<row><a>1</a><b>2</b><c>3</c></row>
<row><a></a><b>5</b><c>6</c></row>
<row><a>7</a><b>8</b><c></c></row>
</table>
现在产生以下(错误的)输出:
NOTICE: col_a: 1 col_b: 2 col_c: 3
NOTICE: col_a: 7 col_b: 5 col_c: 6
NOTICE: col_a: 1 col_b: 8 col_c: 3
NOTICE: col_a: 7 col_b: 2 col_c: 6
NOTICE: col_a: 1 col_b: 5 col_c: 3
NOTICE: col_a: 7 col_b: 8 col_c: 6
一些调试语句显示三个未嵌套的列数组是 {1, 7}, {2, 5, 8} 和 {3, 6}。插入给定行时,没有占位符 NULL 可用作列值。
是否有另一种方法来实现可以正确解释 null 或缺失节点值的取消嵌套?
【问题讨论】:
标签: xml postgresql plpgsql