【问题标题】:sql server parsing xml from select querysql server 从选择查询中解析 xml
【发布时间】:2016-09-11 09:57:40
【问题描述】:

有一个远程 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 以便我得到想要的结果?我想得到这样的东西

select x.EmployeeBoss, count(distinct caseNumber)
来自 AppTable a
内部连接 ​​EmployeeFROMXML x 在 x.Name = a.EmployeeName
由 x.EmployeeBoss 分组

但我没有 EmployeeFROMXML 表,我只有一个类似 XML 的字符串。那么如何将 XML 之类的字符串转换为 sql 表,以便仅在 SELECT 语句的帮助下才能与现有的 AppTable 连接。 (不允许变量声明,因为我只能使用只支持选择语句的网络服务)

【问题讨论】:

  • 正确,已修复...感谢您指出这一点。

标签: sql-server xml


【解决方案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

【讨论】:

  • 这更接近预期的结果,但是我不能使用 CTE,因为 web 服务正在用另一个选择包装选择,所以我最终得到类似 select * from (with xmlDat....) 的东西不会工作。
  • 非常感谢,这就是我要找的!
【解决方案2】:

您可以使用 xquery 函数选择 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 列进行交互,它对我很有帮助。

【讨论】:

  • 问题是我没有 xmlTable 和 xmlColumns。我只有 XML 格式的文本。
  • 您可以使用 Convert(XML, columnName) 将 NVarChar 列转换为 XML。
  • 我没有 nvarchar 列,也没有可供选择的表。我只有一个格式为 XML 的字符串...如何仅使用 select 语句将其转换为 sql 表。 (我知道我可以使用 OpenXML,但你需要声明一个 xml 句柄,调用存储过程等......但我只能使用 select 语句,因为我通过 Web 服务运行)。
猜你喜欢
  • 1970-01-01
  • 2021-01-21
  • 2012-12-16
  • 1970-01-01
  • 1970-01-01
  • 2013-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多