将GROUP BY与XMLCast和XMLQuery一起使用可以得到ORA-22950

时间:2014-12-08 12:40:59

标签: xml oracle xmltype

以下是我想要做的一个例子:

WITH xdata AS
         (SELECT 1 AS a_id,
                 xmltype ('<a>
                    <b>
                        <b_id>1</b_id>
                        <val>2</val>
                    </b>
                    <b>
                        <b_id>1</b_id>
                        <val>3</val>
                    </b>
                 </a>') AS xcol
            FROM DUAL
          UNION ALL
          SELECT 2 AS a_id,
                 xmltype ('<a>
                    <b>
                        <b_id>3</b_id>
                        <val>5</val>
                    </b>
                    <b>
                        <b_id>4</b_id>
                        <val>4</val>
                    </b>
                 </a>') AS xcol
            FROM DUAL)
  SELECT a_id,
         XMLCAST (
             XMLQUERY ('sum($doc/a/b/val/text())'
                       PASSING xcol AS "doc" RETURNING CONTENT) AS INTEGER)
             b_val
    FROM xdata
GROUP BY a_id, xcol;

当我运行上述查询时,我收到错误:

ORA-22950: cannot ORDER objects without MAP or ORDER method

如果删除GROUP BY子句,查询工作正常。

我正在处理的真实世界代码要求我使用GROUP BY子句。我去了this Google search results page中的每个链接,但在XML上下文中找不到任何有用的信息。请帮助我理解为什么这个错误也出现在XMLCast和XMLQuery中。

提前致谢!

2 个答案:

答案 0 :(得分:1)

为了通过值进行聚合,该值必须是可排序/可散列的,这意味着任何两个值必须是可比较的(为了进行排序/散列)。 XMLType不可排序/可排除。当Oracle中的对象/类具有定义的特殊函数maporder时,它是可散列/可排序的。请参阅the respective Oracle documentation

您通过xcol汇总,这是一个XMLType值。因此,您的问题的解决方案是通过其他方式进行汇总。


基于你给我们的混乱信息,我想到了两个解决方案......

解决方案1 ​​

WITH xdata AS
     (SELECT 1 AS a_id,
             xmltype ('<a>
                <b>
                    <b_id>1</b_id>
                    <val>2</val>
                </b>
                <b>
                    <b_id>1</b_id>
                    <val>3</val>
                </b>
             </a>') AS xcol
        FROM DUAL
      UNION ALL
      SELECT 2 AS a_id,
             xmltype ('<a>
                <b>
                    <b_id>3</b_id>
                    <val>5</val>
                </b>
                <b>
                    <b_id>4</b_id>
                    <val>4</val>
                </b>
             </a>') AS xcol
        FROM DUAL)
SELECT a_id,
     sum(XMLCAST (
         XMLQUERY ('sum($doc/a/b/val)'
                   PASSING xcol AS "doc" RETURNING CONTENT) AS INTEGER))
         b_val
FROM xdata
group by a_id;

解决方案2

WITH xdata AS
     (SELECT 1 AS a_id,
             xmltype ('<a>
                <b>
                    <b_id>1</b_id>
                    <val>2</val>
                </b>
                <b>
                    <b_id>1</b_id>
                    <val>3</val>
                </b>
             </a>') AS xcol
        FROM DUAL
      UNION ALL
      SELECT 2 AS a_id,
             xmltype ('<a>
                <b>
                    <b_id>3</b_id>
                    <val>5</val>
                </b>
                <b>
                    <b_id>4</b_id>
                    <val>4</val>
                </b>
             </a>') AS xcol
        FROM DUAL)
select X.a_id, sum(Y.b_val) as b_val
from xdata X
    cross join xmltable(
        '/a/b'
        passing X.xcol
        columns
            b_val integer path 'val'
    ) Y
group by X.a_id;

答案 1 :(得分:0)

提出解决方案可能真的很晚,但是最近我在同一查询中使用 extract xmltype 来检索某些xml数据时遇到了同样的挑战。能够像这样克服它:

解决方案

select result, count(*) from (
   select extract(xmltype(xml_payload),'xpath','namespacedefinition').getStringVal() as result from x_table
) group by result;

当然,不需要包装主查询。

祝你好运!