从包含XML内容的字段创建视图(SQL)

时间:2014-01-14 17:18:05

标签: sql xml database oracle

我正在使用Oracle DBMS,并且有一个表,其中一个字段包含XML代码,因此我希望从该字段创建一个View。同一视图应包含一组属性,如拥有XML的那些属性。 我已经有了一个解决方案,但它太麻烦了(大约有50个字段),并希望加快这个过程。

具有该属性的一段代码 ....

<AREAMEDIC200 titulo="campo1; " valor="False" />
<AREAMEDIC210 titulo="campo2; " valor="False" />
<AREAMEDIC220 titulo="campo3; " valor="True" />

...

SQL的一部分

CREATE VIEW teste AS
Select NPROCESSO,
trim(extract(MENUXML, '//AREAMEDIC200/@valor')) AS c1,
trim(extract(MENUXML, '//AREAMEDIC210/@valor')) AS c2,
trim(extract(MENUXML, '//AREAMEDIC220/@valor')) AS c3,
.....
FROM TABELA1;

任何人都有任何建议可以加快开发速度吗?

问候

1 个答案:

答案 0 :(得分:0)

假设MENUXML的类型为XMLType,并且具有根节点,则可以使用xmltable将值提取为行:

select t.nprocesso, x.titulo, x.valor
from tabela1 t,
xmltable('/TOPLEVEL/*' passing t.menuxml
  columns titulo varchar2(10) path '@titulo',
    valor varchar2(5) path '@valor') x

 NPROCESSO TITULO     VALOR
---------- ---------- -----
         1 campo1;    False 
         1 campo2;    False 
         1 campo3;    True  

然后你可以将它转移到列中,但是你仍然必须在某处列出可能的值 - 值的数量必须被称为解析时间,所以它不能完全灵活:

select *
from (
select t.nprocesso, rtrim(x.titulo, ';') as titulo, x.valor
from tabela1 t,
xmltable('/TOPLEVEL/*' passing t.menuxml
  columns titulo varchar2(10) path '@titulo',
    valor varchar2(5) path '@valor') x
)
pivot (min(valor) as v for (titulo) in ('campo1' as campo1, 'campo2' as campo2,
  'campo3' as campo3))

... 除了导致11.2.0.3中的核心转储(ORA-07445: exception encountered: core dump [evaopn3()+125] [SIGSEGV]如果您感兴趣,除NO_XML_QUERY_REWRITE提示外可能会注意到1580106.1没有帮助。)

由于你实际上并没有说过你的11g,假装一个支点的旧方法仍然有效,但稍微多一些工作:

select nprocesso,
  max(case when titulo = 'campo1; ' then valor end) as campo1,
  max(case when titulo = 'campo2; ' then valor end) as campo2,
  max(case when titulo = 'campo3; ' then valor end) as campo3
from (
select t.nprocesso, x.titulo, x.valor
from tabela1 t,
xmltable('/TOPLEVEL/*' passing t.menuxml
  columns titulo varchar2(10) path '@titulo',
    valor varchar2(5) path '@valor') x
)
group by nprocesso
order by nprocesso;

 NPROCESSO CAMPO1 CAMPO2 CAMPO3
---------- ------ ------ ------
         1 False  False  True   

SQL Fiddle demo。只要包含提示,pivot版本就可以在那里工作(我相信11.2.0.2)。

您只需要为50个可能值中的每一个重复max...子句。不确定你是否会认为这比你现在所做的更容易。

编辑:如果MENUXML确实是varchar2,您可以将其转换为XMLType,并同时添加根节点,以便允许:

...
xmltable('/ROOT/*' passing xmltype('<ROOT>' || t.menuxml || '</ROOT>')
...