【问题标题】:Unnest (xpath()) doesn't identify NULL values correctlyUnnest (xpath()) 不能正确识别 NULL 值
【发布时间】: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


    【解决方案1】:

    这不是UNNEST 的问题,而是xpath 的问题(或者更确切地说,由于)xpath 似乎在返回的数组中不包含 NULL 值。

    SELECT XPATH('/root/table/row/a/text()', '&lt;root&gt;&lt;table&gt;&lt;row&gt;&lt;a&gt;1&lt;/a&gt;&lt;a&gt;&lt;/a&gt;&lt;a&gt;3&lt;/a&gt;&lt;/row&gt;&lt;/table&gt;&lt;/root&gt;'::XML) 返回{1,3}

    解决此问题的一种方法是先对元素执行xpath,然后再访问这些值:

    SELECT (XPATH('/a/text()', u))[1]
    FROM UNNEST(XPATH('/root/table/row/a', '<root><table><row><a>1</a><a></a><a>3</a></row></table></root>'::XML)) u
    

    这将返回 3 行(第二行为 NULL):

    1
    
    3
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多