如何在Oracle XMLTable中使用带有变量的XPath?

时间:2012-12-19 07:24:47

标签: oracle xpath plsql

如何在Oracle XMLTable()中使用带有类似'/ abc / [contract = $ count] / initialValue'的变量的XPath?

例如:

XMLTable('root/level1', PASSING xmlContent 
COLUMNS initial_value varchar2(100) PATH '/abc/[contract = $count]/initialValue' 
)

如何替换/评估$ count运行时?

2 个答案:

答案 0 :(得分:6)

您可以传入变量,只需在传递子句中定义它们:

with table1 AS
  (select xmltype(
  '<abc>
     <def>
        <contract>1</contract>
        <oper>SFO</oper>
        <lmt>limit1</lmt>
     </def>
    <def>
       <contract>2</contract>
       <oper>boston</oper>
       <lmt >limit2</lmt>
    </def>
 </abc>'
 ) xmlcol from dual
 )
 SELECT u.*
   FROM table1
   ,    XMLTable('/abc/def[contract = $count]'
                 PASSING xmlcol, 1 as "count"
                 COLUMNS contract integer path 'contract',
                         oper     VARCHAR2(20) PATH 'oper' ) u 

  CONTRACT OPER               
---------- --------------------
         1 SFO        

答案 1 :(得分:2)

如果在外部pl / sql块中定义“count”变量,则使用table(),因为xmltable路径必须是字符串文字,并且不允许拼接变量。

我假设你的xml结构是

<root>
  <level1>
     <abc>
        <contract>3</contract>
        <initialValue>4</initialValue>
      </abc> 
  </level1>
</root>


SQL> declare
  2    v_count  number := 3;
  3  begin
  4    for r_row in (select extractvalue(value(my_table), '/level1/abc[contract = "' || v_count || '"]/initialValue') xml
  5                    from table(
  6                           xmlsequence(
  7                             extract(XMLType('<root>
  8                      <level1>
  9                         <abc>
 10                            <contract>3</contract>
 11                                          <initialValue>4</initialValue>
 12                          </abc>
 13                      </level1>
 14                      <level1>
 15                         <abc>
 16                            <contract>3</contract>
 17                            <initialValue>7</initialValue>
 18                          </abc>
 19                      </level1>
 20                      <level1>
 21                         <abc>
 22                            <contract>4</contract>
 23                            <initialValue>24</initialValue>
 24                          </abc>
 25                      </level1>
 26                    </root>'),
 27                       '/root/level1'))) my_table)
 28    loop
 29      dbms_output.put_line(r_row.xml);
 30    end loop;
 31  end;
 32  /
4
7

使用xmltable执行此操作的方法不是将其放入XPAth,而是在之后的where子句中进行过滤:

SQL> declare
  2    v_count  number := 3;
  3  begin
  4    for r_row in (select *
  5                    from XMLTable( 'root/level1'  passing xmltype('<root>
  6                      <level1>
  7                         <abc>
  8                            <contract>3</contract>
  9                                          <initialValue>4</initialValue>
 10                          </abc>
 11                      </level1>
 12                      <level1>
 13                         <abc>
 14                            <contract>3</contract>
 15                            <initialValue>7</initialValue>
 16                          </abc>
 17                      </level1>
 18                      <level1>
 19                         <abc>
 20                            <contract>4</contract>
 21                            <initialValue>24</initialValue>
 22                          </abc>
 23                      </level1>
 24                    </root>')
 25                    columns initial_value varchar2(100) PATH 'abc/initialValue',
 26                            contract      varchar2(100) PATH 'abc/contract')
 27                   where contract = v_count)
 28    loop
 29      dbms_output.put_line(r_row.initial_value);
 30    end loop;
 31  end;
 32  /
4
7