从 Oracle XMLType 共享数据
Shreading Data From Oracle XMLType
我一直在为这个(剩下的)而烦恼,想知道你是否看到了我在 Oracle 的 XPath 逻辑中没有看到的东西。我通过Oracle的文档研究了各种功能和XPath方法,但无济于事。
在下面的示例中,table pg_xml_stg 包含属性 pressganey_xml (XMLType)。以下内容示例:
<PATIENTLEVELDATA>
<SURVEY_ID>826434950</SURVEY_ID>
<CLIENT_ID>7145</CLIENT_ID>
<SERVICE>IN</SERVICE>
<RECDATE>2014-11-26</RECDATE>
<DISDATE>2014-07-04</DISDATE>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>5</VALUE>
这是一个将数据下拉到响应级别的查询,但不包括来自患者级别 (survey_id) 的数据。不确定我的 XPATH 字符串是否已关闭,或者实际的 xmlsequence 调用实际上没有将数据拉到 ANALYSIS 之上。
SELECT extractvalue (Value (pg), '//VARNAME/text()') as PG_VARNAME
,extractvalue (Value (pg), '//VALUE/text()') as PG_VARNAME
,extractvalue (Value (pg), '../../SURVEY_ID/text()') as PG_VARNAME
FROM v500.pg_xml_stg
,TABLE (xmlsequence (extract (pressganey_xml, '//PATIENTLEVELDATA/ANALYSIS/RESPONSE'))) pg
PG_VARNAME PG_VARNAME PG_VARNAME
A1 5
A2 5
D1 5
D2 5
D3 5
I1 5
I17 5
I6 5
我可以通过索引 VARRAY 在下面的查询中同时获得两者,但它不允许超过级别 1 的任何内容。
SELECT extractvalue (Value (pg), '//PATIENTLEVELDATA/SURVEY_ID/text()') as PG_SURVEY_ID
,extractvalue (Value (pg), '//PATIENTLEVELDATA/ANALYSIS[1]/RESPONSE[1]/VARNAME[1]/text()') as PG_VARNAME
,extractvalue (Value (pg), '//PATIENTLEVELDATA/ANALYSIS[1]/RESPONSE[1]/VALUE[1]/text()') as PG_VALUE
FROM v500.pg_xml_stg
, TABLE (xmlsequence (extract (pressganey_xml, '*/PATIENTLEVELDATA'))) pg
PG_SURVEY_ID PG_VARNAME PG_VALUE
826434950 A1 5
830145105 A1 5
842152499 A1 4
846003814 A1 5
850619251 D1 3
850711623 A1 4
851482310 A1 5
谢谢,
布莱恩
在您的第一个查询中,调查 ID 不可用,因为 pg
仅包含响应;原始 XML 中上面的数据无法用于 extractvalue()
调用,因为它没有被传递。您所做的类似于将值的 substr 传递给函数并期望该函数知道整个原始字符串。
如您所知,在第二个查询中您只指定了每个节点名称的第一个实例。并且因为每个级别都有多个节点,所以无论如何您都不能使用 extractvalue()
,并且尝试获取多个节点会抛出 ORA-19025: EXTRACTVALUE returns value of only one node
。而且 extractvalue()
is deprecated 无论如何。
要获取多个值,您可以使用 the XMLTable()
function 将您的 XML 层次结构转换为更像关系数据的东西。
您的 XML 代码段没有显示整个结构或节点如何重复,但从您的查询及其结果向后工作,类似这样的内容可能足以让您了解总体思路:
<?xml version="1.0"?>
<DATA>
<PATIENTLEVELDATA>
<SURVEY_ID>826434950</SURVEY_ID>
<CLIENT_ID>7145</CLIENT_ID>
<SERVICE>IN</SERVICE>
<RECDATE>2014-11-26</RECDATE>
<DISDATE>2014-07-04</DISDATE>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>5</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>A2</VARNAME>
<VALUE>6</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>D1</VARNAME>
<VALUE>7</VALUE>
</RESPONSE>
</ANALYSIS>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>8</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>A2</VARNAME>
<VALUE>9</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>D1</VARNAME>
<VALUE>10</VALUE>
</RESPONSE>
</ANALYSIS>
</PATIENTLEVELDATA>
<PATIENTLEVELDATA>
<SURVEY_ID>830145105</SURVEY_ID>
<CLIENT_ID>7146</CLIENT_ID>
<SERVICE>IN</SERVICE>
<RECDATE>2014-11-27</RECDATE>
<DISDATE>2014-07-04</DISDATE>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>3</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>A2</VARNAME>
<VALUE>4</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>D1</VARNAME>
<VALUE>7</VALUE>
</RESPONSE>
</ANALYSIS>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>11</VALUE>
</RESPONSE>
</ANALYSIS>
</PATIENTLEVELDATA>
</DATA>
然后像这样的查询:
select x.*
from pg_xml_stg pxs
cross join xmltable('for $i in //PATIENTLEVELDATA, $j in $i/ANALYSIS/RESPONSE
return <tmp
pg_survey_id="{$i/SURVEY_ID}"
pg_varname="{$j/VARNAME}"
pg_value="{$j/VALUE}"
/>'
passing pxs.pressganey_xml
columns
pg_survey_id number path '/tmp/@pg_survey_id',
pg_varname varchar2(10) path '/tmp/@pg_varname',
pg_value number path '/tmp/@pg_value'
) x;
获取输出:
PG_SURVEY_ID PG_VARNAME PG_VALUE
------------ ---------- ----------
826434950 A1 5
826434950 A2 6
826434950 D1 7
826434950 A1 8
826434950 A2 9
826434950 D1 10
830145105 A1 3
830145105 A2 4
830145105 D1 7
830145105 A1 11
10 rows selected
所有响应 VARNAME
/VALUE
与其父节点的 SURVEY_ID
配对。
XPath 通过使用 $i
获取 PATIENTLEVEL
个节点,然后在这些 $j
中获取与每个节点相关的 RESPONSE
个节点来扁平化数据。您感兴趣的值组合为 return
子句中虚拟 tmp
节点的属性;它为每个响应生成类似这样的内容:
<tmp pg_survey_id="826434950" pg_varname="A1" pg_value="5" />
passing
子句刚刚从您的 table 中识别出 XMLType 列并将其传递到 XPath 中。 columns
子句将虚拟 tmp
节点的属性转换为关系列。
我猜调查 ID 和响应值是数字,但您可以调整所有这些数据类型以匹配您实际拥有的数据。
我一直在为这个(剩下的)而烦恼,想知道你是否看到了我在 Oracle 的 XPath 逻辑中没有看到的东西。我通过Oracle的文档研究了各种功能和XPath方法,但无济于事。
在下面的示例中,table pg_xml_stg 包含属性 pressganey_xml (XMLType)。以下内容示例:
<PATIENTLEVELDATA>
<SURVEY_ID>826434950</SURVEY_ID>
<CLIENT_ID>7145</CLIENT_ID>
<SERVICE>IN</SERVICE>
<RECDATE>2014-11-26</RECDATE>
<DISDATE>2014-07-04</DISDATE>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>5</VALUE>
这是一个将数据下拉到响应级别的查询,但不包括来自患者级别 (survey_id) 的数据。不确定我的 XPATH 字符串是否已关闭,或者实际的 xmlsequence 调用实际上没有将数据拉到 ANALYSIS 之上。
SELECT extractvalue (Value (pg), '//VARNAME/text()') as PG_VARNAME
,extractvalue (Value (pg), '//VALUE/text()') as PG_VARNAME
,extractvalue (Value (pg), '../../SURVEY_ID/text()') as PG_VARNAME
FROM v500.pg_xml_stg
,TABLE (xmlsequence (extract (pressganey_xml, '//PATIENTLEVELDATA/ANALYSIS/RESPONSE'))) pg
PG_VARNAME PG_VARNAME PG_VARNAME
A1 5
A2 5
D1 5
D2 5
D3 5
I1 5
I17 5
I6 5
我可以通过索引 VARRAY 在下面的查询中同时获得两者,但它不允许超过级别 1 的任何内容。
SELECT extractvalue (Value (pg), '//PATIENTLEVELDATA/SURVEY_ID/text()') as PG_SURVEY_ID
,extractvalue (Value (pg), '//PATIENTLEVELDATA/ANALYSIS[1]/RESPONSE[1]/VARNAME[1]/text()') as PG_VARNAME
,extractvalue (Value (pg), '//PATIENTLEVELDATA/ANALYSIS[1]/RESPONSE[1]/VALUE[1]/text()') as PG_VALUE
FROM v500.pg_xml_stg
, TABLE (xmlsequence (extract (pressganey_xml, '*/PATIENTLEVELDATA'))) pg
PG_SURVEY_ID PG_VARNAME PG_VALUE
826434950 A1 5
830145105 A1 5
842152499 A1 4
846003814 A1 5
850619251 D1 3
850711623 A1 4
851482310 A1 5
谢谢,
布莱恩
在您的第一个查询中,调查 ID 不可用,因为 pg
仅包含响应;原始 XML 中上面的数据无法用于 extractvalue()
调用,因为它没有被传递。您所做的类似于将值的 substr 传递给函数并期望该函数知道整个原始字符串。
如您所知,在第二个查询中您只指定了每个节点名称的第一个实例。并且因为每个级别都有多个节点,所以无论如何您都不能使用 extractvalue()
,并且尝试获取多个节点会抛出 ORA-19025: EXTRACTVALUE returns value of only one node
。而且 extractvalue()
is deprecated 无论如何。
要获取多个值,您可以使用 the XMLTable()
function 将您的 XML 层次结构转换为更像关系数据的东西。
您的 XML 代码段没有显示整个结构或节点如何重复,但从您的查询及其结果向后工作,类似这样的内容可能足以让您了解总体思路:
<?xml version="1.0"?>
<DATA>
<PATIENTLEVELDATA>
<SURVEY_ID>826434950</SURVEY_ID>
<CLIENT_ID>7145</CLIENT_ID>
<SERVICE>IN</SERVICE>
<RECDATE>2014-11-26</RECDATE>
<DISDATE>2014-07-04</DISDATE>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>5</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>A2</VARNAME>
<VALUE>6</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>D1</VARNAME>
<VALUE>7</VALUE>
</RESPONSE>
</ANALYSIS>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>8</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>A2</VARNAME>
<VALUE>9</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>D1</VARNAME>
<VALUE>10</VALUE>
</RESPONSE>
</ANALYSIS>
</PATIENTLEVELDATA>
<PATIENTLEVELDATA>
<SURVEY_ID>830145105</SURVEY_ID>
<CLIENT_ID>7146</CLIENT_ID>
<SERVICE>IN</SERVICE>
<RECDATE>2014-11-27</RECDATE>
<DISDATE>2014-07-04</DISDATE>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>3</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>A2</VARNAME>
<VALUE>4</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>D1</VARNAME>
<VALUE>7</VALUE>
</RESPONSE>
</ANALYSIS>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>11</VALUE>
</RESPONSE>
</ANALYSIS>
</PATIENTLEVELDATA>
</DATA>
然后像这样的查询:
select x.*
from pg_xml_stg pxs
cross join xmltable('for $i in //PATIENTLEVELDATA, $j in $i/ANALYSIS/RESPONSE
return <tmp
pg_survey_id="{$i/SURVEY_ID}"
pg_varname="{$j/VARNAME}"
pg_value="{$j/VALUE}"
/>'
passing pxs.pressganey_xml
columns
pg_survey_id number path '/tmp/@pg_survey_id',
pg_varname varchar2(10) path '/tmp/@pg_varname',
pg_value number path '/tmp/@pg_value'
) x;
获取输出:
PG_SURVEY_ID PG_VARNAME PG_VALUE
------------ ---------- ----------
826434950 A1 5
826434950 A2 6
826434950 D1 7
826434950 A1 8
826434950 A2 9
826434950 D1 10
830145105 A1 3
830145105 A2 4
830145105 D1 7
830145105 A1 11
10 rows selected
所有响应 VARNAME
/VALUE
与其父节点的 SURVEY_ID
配对。
XPath 通过使用 $i
获取 PATIENTLEVEL
个节点,然后在这些 $j
中获取与每个节点相关的 RESPONSE
个节点来扁平化数据。您感兴趣的值组合为 return
子句中虚拟 tmp
节点的属性;它为每个响应生成类似这样的内容:
<tmp pg_survey_id="826434950" pg_varname="A1" pg_value="5" />
passing
子句刚刚从您的 table 中识别出 XMLType 列并将其传递到 XPath 中。 columns
子句将虚拟 tmp
节点的属性转换为关系列。
我猜调查 ID 和响应值是数字,但您可以调整所有这些数据类型以匹配您实际拥有的数据。