尝试循环通过 XML 提取 PLSQL 中的值
Posted
技术标签:
【中文标题】尝试循环通过 XML 提取 PLSQL 中的值【英文标题】:Trying to loop through XML to extract values in PLSQL 【发布时间】:2016-11-15 16:27:15 【问题描述】:我正在尝试遍历 XML 并提取 UUID。我有以下内容,它循环正确的次数并每次打印一个空白行。为什么不提取 UUID 节点的文本值?
DECLARE
X XMLTYPE := XMLTYPE('<?xml version="1.0" ?>
<StatusUp>
<G_UUIDs>
<UUID>1 test 1</UUID>
<UUID>2 test 2</UUID>
<UUID>3 test 3 </UUID>
<UUID>4 test 4 </UUID>
</G_UUIDs>
</StatusUp>');
BEGIN
FOR r IN (SELECT EXTRACTVALUE(VALUE(p), 'StatusUp/G_UUIDs/UUID/text()') AS uuid
FROM TABLE(XMLSEQUENCE(EXTRACT(X, '//StatusUp/G_UUIDs/UUID'))) p)
LOOP
DBMS_OUTPUT.PUT_LINE('UUID' || r.uuid);
END LOOP;
END;
【问题讨论】:
【参考方案1】:您已经在 FROM 语句中从 XML 中提取了 UUID,而在 select 中,形象地说,您现在只有四行
<UUID> n test n </UUID>
所以提取数据的正确方法是:
DECLARE
X XMLTYPE := XMLTYPE(
'<?xml version="1.0" ?>
<StatusUp>
<G_UUIDs>
<UUID>1 test 1</UUID>
<UUID>2 test 2</UUID>
<UUID>3 test 3 </UUID>
<UUID>4 test 4 </UUID>
</G_UUIDs>
</StatusUp>');
BEGIN
FOR r IN (SELECT
EXTRACTVALUE(
VALUE(p),
--'StatusUp/G_UUIDs/UUID/text()') AS uuid
'/UUID/text()') AS uuid
FROM
TABLE(
XMLSEQUENCE(
EXTRACT(
X,
'//StatusUp/G_UUIDs/UUID')
)
) p
)
LOOP
DBMS_OUTPUT.PUT_LINE(r.uuid);
END LOOP;
END;
【讨论】:
【参考方案2】:如果您要将其转换为 sql 语句并运行它,如下所示:
WITH sample_data AS (SELECT XMLTYPE('<?xml version="1.0" ?>
<StatusUp>
<G_UUIDs>
<UUID>1 test 1</UUID>
<UUID>2 test 2</UUID>
<UUID>3 test 3 </UUID>
<UUID>4 test 4 </UUID>
</G_UUIDs>
</StatusUp>') x FROM dual)
SELECT p.*,
EXTRACTVALUE(VALUE(p), 'StatusUp/G_UUIDs/UUID/text()') AS uuid
FROM sample_data sd,
TABLE(XMLSEQUENCE(EXTRACT(sd.x, '//StatusUp/G_UUIDs/UUID'))) p;
很容易发现问题:
COLUMN_VALUE UUID
------------------------ ----------
<UUID>1 test 1</UUID>
<UUID>2 test 2</UUID>
<UUID>3 test 3 </UUID>
<UUID>4 test 4 </UUID>
即您正在尝试从仅包含节点 UUID
的 xml 中提取节点 StatusUp/G_UUIDs/UUID
。相反,如果您更正要查询的节点,您会得到正确的结果:
DECLARE
X XMLTYPE := XMLTYPE('<?xml version="1.0" ?>
<StatusUp>
<G_UUIDs>
<UUID>1 test 1</UUID>
<UUID>2 test 2</UUID>
<UUID>3 test 3 </UUID>
<UUID>4 test 4 </UUID>
</G_UUIDs>
</StatusUp>');
BEGIN
FOR r IN (SELECT EXTRACTVALUE(VALUE(p), 'UUID/text()') AS uuid
FROM TABLE(XMLSEQUENCE(EXTRACT(X, '//StatusUp/G_UUIDs/UUID'))) p)
LOOP
DBMS_OUTPUT.PUT_LINE('UUID' || r.uuid);
END LOOP;
END;
/
UUID1 test 1
UUID2 test 2
UUID3 test 3
UUID4 test 4
但是,不推荐使用 EXTRACT 和 EXTRACTVALUE - 您应该改用 XMLTABLE:
DECLARE
X XMLTYPE := XMLTYPE('<?xml version="1.0" ?>
<StatusUp>
<G_UUIDs>
<UUID>1 test 1</UUID>
<UUID>2 test 2</UUID>
<UUID>3 test 3 </UUID>
<UUID>4 test 4 </UUID>
</G_UUIDs>
</StatusUp>');
BEGIN
FOR r IN (SELECT *
FROM XMLTABLE('//StatusUp/G_UUIDs/UUID'
PASSING x
COLUMNS uuid varchar2(10) PATH '.'))
LOOP
DBMS_OUTPUT.PUT_LINE('UUID' || r.uuid);
END LOOP;
END;
/
UUID1 test 1
UUID2 test 2
UUID3 test 3
UUID4 test 4
您应该尝试运行的等效查询:
WITH sample_data AS (SELECT XMLTYPE('<?xml version="1.0" ?>
<StatusUp>
<G_UUIDs>
<UUID>1 test 1</UUID>
<UUID>2 test 2</UUID>
<UUID>3 test 3 </UUID>
<UUID>4 test 4 </UUID>
</G_UUIDs>
</StatusUp>') x FROM dual)
SELECT *
FROM sample_data sd,
XMLTABLE('//StatusUp/G_UUIDs/UUID'
PASSING sd.x
COLUMNS uuid varchar2(10) PATH '.');
【讨论】:
谢谢,我刚刚发现了 extractvalue 节点错误的问题,正准备回答我自己的问题。我不知道 XMLTABLE 并将查看它。 我在运行 xmltable 建议时遇到错误,具体来说:第 1 行错误 ORA-19114:解析 XQuery 表达式时出错:java.lang.NoClassDefFoundError ORA-06512:第 12 行跨度> 您是否收到我给您的代码的错误?因为这对我来说没有错误。如果是这样,您在哪个版本的 Oracle 上运行它? @bonesit 我在 Oracle 10g 上,是的,我试图运行的正是你的代码。 嗯。它绝对可以在 11.2.0.4 上运行。我希望您尝试一个查询,它相当于我添加到我的问题中的存储过程 - 当您运行它时,您仍然会收到错误吗?以上是关于尝试循环通过 XML 提取 PLSQL 中的值的主要内容,如果未能解决你的问题,请参考以下文章