sql server从select查询中解析xml

时间:2016-09-11 00:13:24

标签: sql-server xml

有一个远程sql server db,我只能通过Web服务访问,并将sql文本传递给它。该服务将传入的sql文本包装到select语句中,并返回查询结果。

例如,如果我想执行:

select employeeName, caseNumber from AppTable

我传入服务'select employeeName, caseNumber, 12344 vendorId from AppTable',服务实际上将执行以下内容:

select * from (select employeeName, caseNumber, 12344 vendorId from AppTable) s where s.vendorId = 12344

要求是每个员工的老板得到所有案件,所以这就像是

select employeeBoss, count(caseNumber) from AppTable group by employeeBoss

问题是employeeBoss没有存储在远程数据库中,我必须通过webservice传递这些信息。 所以我假设我有一个像文本一样的xml,我可以传递给服务:

<Employee>
   <Name>John Doe</Name>
   <EmployeeBoss>Bill G</EmployeeBoss>
</Employee>
<Employee>
   <Name>Jane Smith</Name>
   <EmployeeBoss>Gordon B</EmployeeBoss>
</Employee>
<Employee>
   <Name>Derek Edward</Name>
   <EmployeeBoss>Gordon B</EmployeeBoss>
</Employee>

有没有办法在select语句中解析XML,以便获得所需的结果?我想要得到这样的东西

  

选择x.EmployeeBoss,count(distinct caseNumber)
    来自AppTable a   内部联接EmployeeFROMXML x on x.Name = a.EmployeeName
  分组由x.EmployeeBoss

但是我没有EmployeeFROMXML表,我只有一个像XML这样的字符串。那么我怎样才能将XML之类的字符串转换为sql表,只有借助SELECT语句才能与现有的AppTable连接。 (不允许变量声明,因为我只能使用仅支持select语句的Web服务)

2 个答案:

答案 0 :(得分:1)

你可以这样做。

with xmlDat as (--read as xml
select cast(
'<Employees>
    <Employee>
       <Name>John Doe</Name>
       <EmployeeBoss>Bill G</EmployeeBoss>
    </Employee>
    <Employee>
       <Name>Jane Smith</Name>
       <EmployeeBoss>Gordon B</EmployeeBoss>
    </Employee>
    <Employee>
       <Name>Derek Edward</Name>
       <EmployeeBoss>Gordon B</EmployeeBoss>
    </Employee>
</Employees>' as xml) e
)
,emp as (--tabulate
select t.v.value('Name[1]','varchar(100)') Name,
t.v.value('EmployeeBoss[1]','varchar(100)') EmployeeBoss
from xmlDat cross apply e.nodes('Employees/Employee') t(v)
)--and use
select emp.EmployeeBoss, count(distinct caseNumber)
from emp
inner join AppTable a on emp.Name = a.EmployeeName
group by emp.EmployeeBoss

更新

同样没有CTE

select emp.EmployeeBoss, count(distinct caseNumber) from 
(select t.v.value('Name[1]','varchar(100)') Name,
t.v.value('EmployeeBoss[1]','varchar(100)') EmployeeBoss
from  
(select cast(
'<Employees>
    <Employee>
       <Name>John Doe</Name>
       <EmployeeBoss>Bill G</EmployeeBoss>
    </Employee>
    <Employee>
       <Name>Jane Smith</Name>
       <EmployeeBoss>Gordon B</EmployeeBoss>
    </Employee>
    <Employee>
       <Name>Derek Edward</Name>
       <EmployeeBoss>Gordon B</EmployeeBoss>
    </Employee>
</Employees>' as xml) e
) xdat  cross apply e.nodes('Employees/Employee') t(v)) emp
inner join AppTable a on emp.Name = a.EmployeeName
group by emp.EmployeeBoss

答案 1 :(得分:0)

您可以使用xquery funcitons

选择xml值
SELECT 
[xmlColumn].value('(/Employee//EmployeeBoss/node())[1]', 'varchar(max)') as boss
FROM AppTable a
INNER JOIN xmlTable on [xmlColumn].value('(/Employee//Name/node())[1]', 'varchar(max)') as name = a.EmployeeName

此查询尚未经过测试,但我之前使用过.value()函数与XML列进行交互,这对我很有用。