在SQL

时间:2016-02-01 15:24:31

标签: sql-server xml

我正在读取Sql中的xml数据。

这是我的xml:

Declare @MainXml XML = 
'<?xml version="1.0" encoding="utf-8"?>
  <result>
   <details>
     <admin>
        <code>555</code>
     </admin>
    <claimhistory>
        <claim id="1" number="100">
            <account>Closed</account>           
        </claim>        
        <claim id="2" number="200">         
            <account>Closed</account>                       
         </claim>        
     </claimhistory>
 </details>
</result>'

读取这样的数据:

select 
    C.X.value('(admin/code)[1]', 'varchar(max)') as Code,
    A.X.value('@id', 'varchar(max)') as Id,
    A.X.value('@number', 'varchar(max)') as No,            
    A.X.value('(account)[1]', 'varchar(max)') as Status
from 
    @MainXml.nodes('result/details') as C(X)
cross apply 
    C.X.nodes('claimhistory/claim') as A(X)

这是回归:

Code  Id  No  Status 
---------------------
555   1   100  Closed
555   2   200  Closed

存储过程包含上述代码。

此处数据表变量用作存储过程的输入。它包含id和名称。

 Declare @dtValue As [dbo].[DataTableDetails]
 Insert Into @dtValue(Requested_Id, Name) Values(1, 'Tim');
 Insert Into @dtValue(Requested_Id, Name) Values(2, 'Joe');

我想基于匹配xml的Id来输入这些名称来选择查询。

预期产出 -

Code  Id  No   Status   Name
----------------------------
555   1   100  Closed   Tim
555   2   200  Closed   Joe

目前 - 从xml插入选定的记录后,我正在使用更新查询但是表包含超过一百万条记录,因此它现在正在影响性能。

请建议我。

编辑:

尝试使用加入 - [在选择查询中添加以下行]

Select 
    C.X.value('(admin/code)[1]', 'varchar(max)') as Code,
    A.X.value('@id', 'varchar(max)') as Id,
    A.X.value('@number', 'varchar(max)') as No,            
    A.X.value('(account)[1]', 'varchar(max)') as Status,
    CA.Name
from 
    @MainXml.nodes('result/details') as C(X)
cross apply 
    C.X.nodes('claimhistory/claim') as A(X)
join 
    @dtValue CA on CA.Requested_Id = A.X.value('@id', 'varchar(max)')

1 个答案:

答案 0 :(得分:1)

我建议重构你从XML中选择的方式:

select 
    C.X.value('(../../admin/code)[1]', 'varchar(max)') as Code,
    C.X.value('@id', 'varchar(max)') as Id,
    C.X.value('@number', 'varchar(max)') as No,            
    C.X.value('(account)[1]', 'varchar(max)') as Status,
    dt.Name
from 
    @MainXml.nodes('result/details/claimhistory/claim') as C(X)
INNER JOIN @dtValue dt
ON dt.Requested_Id = C.X.value('(@id)[1]', 'int')

实际上想要CROSS APPLY子节点,您希望它们是您选择的主要部分(即每claim个元素一行) - 然后很容易根据祖父节点选择得到Code值,然后你可以正确地INNER JOIN你的表变量。

完整样本:

Declare @MainXml XML = 
'<?xml version="1.0" encoding="utf-8"?>
  <result>
   <details>
     <admin>
        <code>555</code>
     </admin>
    <claimhistory>
        <claim id="1" number="100">
            <account>Closed</account>           
        </claim>        
        <claim id="2" number="200">         
            <account>Closed</account>                       
         </claim>        
     </claimhistory>
 </details>
</result>'

DECLARE @dtValue TABLE (Requested_Id int, Name varchar(10))

 Insert Into @dtValue(Requested_Id, Name) Values(1, 'Tim'), (2, 'Joe');

select 
    C.X.value('(../../admin/code)[1]', 'varchar(max)') as Code,
    C.X.value('@id', 'varchar(max)') as Id,
    C.X.value('@number', 'varchar(max)') as No,            
    C.X.value('(account)[1]', 'varchar(max)') as Status,
    dt.Name
from 
    @MainXml.nodes('result/details/claimhistory/claim') as C(X)
INNER JOIN @dtValue dt
ON dt.Requested_Id = C.X.value('(@id)[1]', 'int')