SQL Server XML查询未返回预期结果

时间:2018-11-01 07:27:19

标签: sql-server xml xml-parsing qxmlquery

我的数据库FlowDetailParameter中有一列具有XML类型。我的表具有一列FlowDetailParameter和三行,其中包含以下数据:

row 1

<ArrayOfFlowDetailParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <FlowDetailParameters>
    <DepartmentId>7</DepartmentId>
    <UserId>6</UserId>
    <Username>4</Username>
    <FullName>کارشناس  معاینه فنی</FullName>
    <ConfirmDateTime>2018-11-01T10:45:29.7371421+03:30</ConfirmDateTime>
    <Comment>اولین IP تاییدی</Comment>
    <Status>Accept</Status>
  </FlowDetailParameters>
  <FlowDetailParameters>
    <DepartmentId>3</DepartmentId>
    <UserId xsi:nil="true" />
    <Username />
    <FullName />
    <ConfirmDateTime xsi:nil="true" />
    <Comment />
    <Status>Pending</Status>
    <AttachmentId />
  </FlowDetailParameters>
</ArrayOfFlowDetailParameters>

row 2

<ArrayOfFlowDetailParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <FlowDetailParameters>
    <DepartmentId>7</DepartmentId>
    <UserId>6</UserId>
    <Username>4</Username>
    <FullName>کارشناس  معاینه فنی</FullName>
    <ConfirmDateTime>2018-11-01T10:45:40.437481+03:30</ConfirmDateTime>
    <Comment>دومین IP تاییدی</Comment>
    <Status>Accept</Status>
  </FlowDetailParameters>
  <FlowDetailParameters>
    <DepartmentId>3</DepartmentId>
    <UserId xsi:nil="true" />
    <Username />
    <FullName />
    <ConfirmDateTime xsi:nil="true" />
    <Comment />
    <Status>Pending</Status>
    <AttachmentId />
  </FlowDetailParameters>
</ArrayOfFlowDetailParameters>


row 3

<ArrayOfFlowDetailParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <FlowDetailParameters>
    <DepartmentId>7</DepartmentId>
    <UserId xsi:nil="true" />
    <Username />
    <FullName />
    <ConfirmDateTime xsi:nil="true" />
    <Comment />
    <Status>Pending</Status>
    <AttachmentId />
  </FlowDetailParameters>
  <FlowDetailParameters>
    <DepartmentId>3</DepartmentId>
    <UserId xsi:nil="true" />
    <Username />
    <FullName />
    <ConfirmDateTime xsi:nil="true" />
    <Comment />
    <Status />
    <AttachmentId />
  </FlowDetailParameters>
</ArrayOfFlowDetailParameters>

我想找到departmentId=3 and status=Pending,所以预期结果应该返回2行。这是我的查询:

    select  Requests.*   from Requests

 where    
  ((SELECT count(*)   
 FROM Requests t
    CROSS APPLY t.FlowDetailParameter.nodes ('/ArrayOfFlowDetailParameters/FlowDetailParameters') x(v)
where    x.v.value('(DepartmentId/text())[1]', 'bigint')=3   and  x.v.value('(Status/text())[1]', 'varchar(50)') = 'Pending') >0)

但是我的查询返回所有行(3行),为什么?

1 个答案:

答案 0 :(得分:1)

首先回答您的问题“为什么?”:

您的子查询不是与相关的子查询。没有从外部SELECT到当前行的连接。因此-假设至少有1行满足您的条件-这将始终提供count>0

尽管您的方法可以纠正,但我建议使用XML方法.exist()并将过滤器提供为XPath/XQuery

SELECT * 
FROM Requests r
WHERE r.FlowDetailParameter.exist(N'/ArrayOfFlowDetailParameters
                                    /FlowDetailParameters[(DepartmentId/text())[1]=3 
                                                          and (Status/text())[1]="Pending"]')=1;

这将检查给定条件是否存在任何<FlowDetailParameters>

如果要动态介绍过滤器,可以使用sql:variable()sql:column()代替3"Pending"

DECLARE @depId INT=3;
DECLARE @status VARCHAR(100)='Pending';

SELECT * 
FROM Requests r
WHERE r.FlowDetailParameter.exist(N'/ArrayOfFlowDetailParameters
                                    /FlowDetailParameters[(DepartmentId/text())[1]=sql:variable("@depId")
                                                          and (Status/text())[1]=sql:variable("@status")]')=1