一个客户要求从数据库中转储一堆带有不同列的数据。只要是SQL,一切都很好,也很容易,但是我遇到了一个问题,其中对于两个请求的值,我需要从XML文件中提取它。我刚上班,进入公司并没有太多帮助,而且我想在这里给我的老板留下深刻的印象,所以很多事情都危在旦夕。
这是XML文件的一个片段:
<record xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" runtimeVersion="2">
<insureds>
<insured uid="xxx" category="000" name="this name" index="0">
<dimensions>
<dimension id="name">
<value xsi:type="xsd:string">Morten</value>
</dimension>
<dimension id="price">
<value xsi:type="xsd:decimal">20</value>
</dimension>
<dimension id="duration">
<value xsi:type="xsd:decimal">10</value>
</dimension>
</dimensions>
</insured>
<insured uid="xxx" category="000" name="this other name" index="1">
<dimensions>
<dimension id="price">
<value xsi:type="xsd:decimal">40</value>
</dimension>
<dimension id="name">
<value xsi:type="xsd:string">Casper</value>
</dimension>
</dimensions>
</insured>
<insured uid="xxx" category="000" name="this last name" index="2">
<dimensions>
<dimension id="price">
<value xsi:type="xsd:decimal">0</value>
</dimension>
</dimensions>
</insured>
对于每种XML,我都希望其中的值是id =“ price”。但是,我的问题是XML随时间而变化,因此对于所有示例而言,价格都不是相同的索引值。相反,我需要在每个XML中找到FIRST TIME id =“ price”的值(因为可以有多个保险/尺寸/价格,并且第一个实例可以移动到新位置)。因此,在上面的示例中,我正在寻找值20。
我得到了下面的工作,但不幸的是,它仅在“价格”处于位置[36]的情况下有效,在生产500000条记录的过程中它已经移动了很多次...
SELECT Xml.value('(/record/insureds/insured/dimensions/dimension/value) [36]',
'varchar(max)') AS 'Price'
我正在尝试根据一些在线示例对其进行修改,这就是我得到的:
SELECT Xml.value('(/record/insureds/insured/dimensions/dimension/@id=@trip_cost)[1]',
'varchar(max)') AS 'Price'
这给了我一个错误:“不支持顶级属性节点。”
现在,我被困住了...关于如何实现获取第一个维度id =“ price”的值的目的的任何想法,无论它在XML中的位置如何?
任何提示,想法或其他类似的东西都非常感谢!
**编辑-这已通过@JeroenMostert的评论**
解决。答案 0 :(得分:2)
使用.value()
将返回一个单个值。您的问题对我来说还不是很清楚,但是我的魔幻水晶球告诉我,您可能正在寻找这个:
DECLARE @xml XML=
'<record xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" runtimeVersion="2">
<insureds>
<insured uid="xxx" category="000" name="this name" index="0">
<dimensions>
<dimension id="name">
<value xsi:type="xsd:string">Morten</value>
</dimension>
<dimension id="price">
<value xsi:type="xsd:decimal">20</value>
</dimension>
<dimension id="duration">
<value xsi:type="xsd:decimal">10</value>
</dimension>
</dimensions>
</insured>
<insured uid="xxx" category="000" name="this other name" index="1">
<dimensions>
<dimension id="price">
<value xsi:type="xsd:decimal">40</value>
</dimension>
<dimension id="name">
<value xsi:type="xsd:string">Casper</value>
</dimension>
</dimensions>
</insured>
<insured uid="xxx" category="000" name="this last name" index="2">
<dimensions>
<dimension id="price">
<value xsi:type="xsd:decimal">0</value>
</dimension>
</dimensions>
</insured>
</insureds>
</record>';
-此查询将以经典的 entity-value 列表返回所有内容的派生表(嗯,其余内容取决于您,但应该很容易)。您可以将其打包到CTE中,并对派生表使用任何类型的WHERE
:
SELECT i.value('@uid','varchar(max)') AS insured_uid
,d.value('@id','varchar(max)') AS dimension_id
,d.value('(value/text())[1]','varchar(max)') AS dimension_value
FROM @xml.nodes('/record/insureds/insured') A(i)
CROSS APPLY i.nodes('dimensions/dimension') B(d);
-这将找到所有<dimension>
个节点,其中有一个值为@id
的属性"price"
并列出以下值:
SELECT d.value('(value/text())[1]','varchar(max)') AS dimension_value
FROM @xml.nodes('//dimension[@id="price"]') A(d);
如果这对您没有帮助,最好将预期的输出拟合包括到所提供的样本数据中。最好是MCVE(一个独立,经过简化但完整的示例,如我上面提供的代码)。