SQL 服务器 xml 查询没有 return 预期结果
SQL Server xml query doesn't return expected result
我的数据库 FlowDetailParameter
中有一列 XML 类型。我的 table 一列 FlowDetailParameter
和 3 行包含这些数据:
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
,所以预期的结果应该是 return 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)
但是我的查询 return 所有行(3 行)为什么?
第一个回答你的问题"why?":
您的子查询不是相关子查询。没有从外部 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
我的数据库 FlowDetailParameter
中有一列 XML 类型。我的 table 一列 FlowDetailParameter
和 3 行包含这些数据:
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
,所以预期的结果应该是 return 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)
但是我的查询 return 所有行(3 行)为什么?
第一个回答你的问题"why?":
您的子查询不是相关子查询。没有从外部 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