Reputation: 178
i have a problem with SQL/XML and Oracle. I use the example from Oracle with dept and emp. The situation at the beginning: I want a xml with department and there employees:
SELECT Xmlelement("employees", dept.deptno, Xmlagg(
Xmlelement("employee", ename))).
getStringVal()
FROM emp
INNER JOIN dept
ON dept.deptno = emp.deptno
GROUP BY dept.deptno;
Now I want all departments, even if there aren't any employees (right outer join). Moreover I want some attributes for the employees:
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;
But now the department with no employees has a empty tag "employee". I have a solution for this problem:
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;
Now I have no empty tag, but I can't place the attributes that I want. Is there any solution for this problem?
Best regards ses
Upvotes: 3
Views: 1778
Reputation: 191235
You can use a case expression to not generate the rogue <employee/>
node in the first place:
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>
Upvotes: 2
Reputation: 21043
Using this answer you may add the DELETXML
to your second query
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;
sample output
<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>
Upvotes: 2