【问题标题】:SQL Oracle XML empty tags and attributesSQL Oracle XML 空标签和属性
【发布时间】:2026-01-07 12:55:02
【问题描述】:

我对 SQL/XML 和 Oracle 有疑问。 我将 Oracle 的示例与 dept 和 emp 一起使用。 一开始的情况: 我想要一个带有部门和员工的 xml:

SELECT Xmlelement("employees", dept.deptno, Xmlagg(
       Xmlelement("employee", ename))).
       getStringVal()
FROM   emp
       INNER JOIN dept
               ON dept.deptno = emp.deptno
GROUP  BY dept.deptno; 

现在我想要所有部门,即使没有任何员工(右外部联接)。此外,我想要员工的一些属性:

SELECT XMLELEMENT("employees", dept.deptno, 
       Xmlagg(
        XMLELEMENT("employee",
             xmlattributes(empno AS "empno", sal AS "salary"), ename)
        )
        ).getStringVal()
FROM   emp
       right outer join dept
                     ON dept.deptno = emp.deptno
GROUP  BY dept.deptno; 

但是现在没有员工的部门有一个空标签“员工”。我有解决这个问题的办法:

SELECT           xmlelement("employees", 
                    xmlattributes(dept.deptno as "Abt"), 
                    xmlagg( xmlforest(ename AS "employee") )
                 ).getstringval()
FROM             emp
RIGHT OUTER JOIN dept
ON               dept.deptno = emp.deptno
GROUP BY         dept.deptno;

现在我没有空标签,但我无法放置我想要的属性。这个问题有解决办法吗?

最好的问候 是的

【问题讨论】:

  • 包含一些示例数据、您现在从这些查询中获得的输出以及您实际尝试实现的输出会很有帮助。
  • 你使用了正确的数据,我使用了相同的

标签: sql xml oracle


【解决方案1】:

您可以使用 case 表达式首先不生成流氓<employee/> 节点:

SELECT XMLELEMENT("employees", dept.deptno, 
         Xmlagg(
           CASE WHEN emp.empno IS NOT NULL THEN
             XMLELEMENT("employee",
               xmlattributes(empno AS "empno", sal AS "salary"), ename)
           END
         )
       ).getStringVal()
FROM   emp
       right outer join dept
                     ON dept.deptno = emp.deptno
GROUP  BY dept.deptno; 

XMLELEMENT("EMPLOYEES",DEPT.DEPTNO,XMLAGG(CASEWHENEMP.EMPNOISNOTNULLTHENXMLELEMENT("EMPLOYEE",XMLATTRIBUTES(EMPNOAS"EMPNO",SALAS"SALARY"),ENAME)END)).GETSTRINGVAL()
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
<employees>10<employee empno="7839" salary="5000">KING</employee><employee empno="7934" salary="1300">MILLER</employee><employee empno="7782" salary="2450">CLARK</employee></employees>
<employees>20<employee empno="7566" salary="2975">JONES</employee><employee empno="7876" salary="1100">ADAMS</employee><employee empno="7369" salary="800">SMITH</employee><employee empno="7902" salary="3000">FORD</employee><employee empno="7788" salary="3000">SCOTT</employee></employees>
<employees>30<employee empno="7698" salary="2850">BLAKE</employee><employee empno="7900" salary="950">JAMES</employee><employee empno="7844" salary="1500">TURNER</employee><employee empno="7654" salary="1250">MARTIN</employee><employee empno="7521" salary="1250">WARD</employee><employee empno="7499" salary="1600">ALLEN</employee></employees>
<employees>40</employees>

【讨论】:

    【解决方案2】:

    使用this answer,您可以将DELETXML 添加到您的第二个查询中

    SELECT DELETEXML(
         XMLELEMENT("employees", dept.deptno, 
           Xmlagg(
            XMLELEMENT("employee",
                 xmlattributes(empno AS "empno", sal AS "salary"), ename)
            )
            ),
             '//*[not(text())][not(*)]'
           ).getStringVal()
    FROM   emp
           right outer join dept
                         ON dept.deptno = emp.deptno
    GROUP  BY dept.deptno;
    

    样本输出

    <employees>1<employee empno="1" salary="100">name1</employee></employees>
    <employees>2<employee empno="2" salary="100">name2</employee></employees>
    <employees>3<employee empno="3" salary="100">name3</employee></employees>
    <employees>4</employees>
    <employees>5</employees>
    

    【讨论】:

    • 这也是可能的,但在我看来,Alex Poole 的答案更好,因为选择直接在查询中。
    • @ses 我也是这么看的。我不会删除我的答案,因为它可能会吸引搜索并指向上述正确答案;)