xml 多条件查询
xml query with more than one condition
这是我的sql数据:
<ArrayOfFlowDetailParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<FlowDetailParameters>
<DepartmentId>23</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>22</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>7</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>18</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
</ArrayOfFlowDetailParameters>
我想找到一个节点,我的意思是 FlowDetailParameters
有 2 个条件,它意味着 departmentid=23 and status=pending
.
这是我的查询:
SELECT
Requests.*
FROM
Requests
WHERE
(@organizationid IS NULL OR OrganizationId = @organizationid)
AND (@DetailStatus IS NULL
OR (EXISTS (SELECT *
FROM Requests.FlowDetailParameter.nodes('/ArrayOfFlowDetailParameters/FlowDetailParameters/DepartmentId') as Parms(DepartmentId)
WHERE DepartmentId.value('.', 'bigint') = @departmentId)
AND EXISTS (SELECT *
FROM Requests.FlowDetailParameter.nodes('/ArrayOfFlowDetailParameters/FlowDetailParameters/Status') as Parms(Status)
WHERE Status.value('.', 'nvarchar(max)') = @DetailStatus)))
但我的查询找到具有 departmentid=23 or status=pending
的节点
如果您想提取适用于您的条件的值和相关 XML 部分,您可以尝试使用此方法:
DECLARE @table table (XmlCol xml )
insert into @table
values
('<ArrayOfFlowDetailParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<FlowDetailParameters>
<DepartmentId>23</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>22</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>7</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>18</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
</ArrayOfFlowDetailParameters>')
;
WITH XmlBreak as
(
SELECT x.v.query('.') TheXml,
x.v.value('(DepartmentId/text())[1]', 'int') DepartmentId,
x.v.value('(Status/text())[1]', 'varchar(50)') Status
FROM @table t
CROSS APPLY XmlCol.nodes ('/ArrayOfFlowDetailParameters/FlowDetailParameters') x(v)
)
SELECT *
FROM XmlBreak
WHERE DepartmentId = 23 and Status = 'Pending'
您可以直接在 XQuery 中将搜索条件应用于子节点:
declare @t table (XData xml);
declare @StatusValue varchar(50) = 'Pending',
@DepartmentId int = 23;
insert into @t (XData)
values (
N'<ArrayOfFlowDetailParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<FlowDetailParameters>
<DepartmentId>23</DepartmentId>
<UserId />
<Username />
<FullName />
<ConfirmDateTime />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>22</DepartmentId>
<UserId />
<Username />
<FullName />
<ConfirmDateTime />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>7</DepartmentId>
<UserId />
<Username />
<FullName />
<ConfirmDateTime />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>18</DepartmentId>
<UserId />
<Username />
<FullName />
<ConfirmDateTime />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
</ArrayOfFlowDetailParameters>');
select a.c.query('.')
from @t t
cross apply t.XData.nodes('/ArrayOfFlowDetailParameters/FlowDetailParameters[
./DepartmentId[1]/text() = sql:variable("@DepartmentId")
and ./Status[1]/text() = sql:variable("@StatusValue")
]') a(c);
此外,由于您可能需要它,我还提供了一个示例来说明如何对此类查询进行参数化。
这是我的sql数据:
<ArrayOfFlowDetailParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<FlowDetailParameters>
<DepartmentId>23</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>22</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>7</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>18</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
</ArrayOfFlowDetailParameters>
我想找到一个节点,我的意思是 FlowDetailParameters
有 2 个条件,它意味着 departmentid=23 and status=pending
.
这是我的查询:
SELECT
Requests.*
FROM
Requests
WHERE
(@organizationid IS NULL OR OrganizationId = @organizationid)
AND (@DetailStatus IS NULL
OR (EXISTS (SELECT *
FROM Requests.FlowDetailParameter.nodes('/ArrayOfFlowDetailParameters/FlowDetailParameters/DepartmentId') as Parms(DepartmentId)
WHERE DepartmentId.value('.', 'bigint') = @departmentId)
AND EXISTS (SELECT *
FROM Requests.FlowDetailParameter.nodes('/ArrayOfFlowDetailParameters/FlowDetailParameters/Status') as Parms(Status)
WHERE Status.value('.', 'nvarchar(max)') = @DetailStatus)))
但我的查询找到具有 departmentid=23 or status=pending
如果您想提取适用于您的条件的值和相关 XML 部分,您可以尝试使用此方法:
DECLARE @table table (XmlCol xml )
insert into @table
values
('<ArrayOfFlowDetailParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<FlowDetailParameters>
<DepartmentId>23</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>22</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>7</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>18</DepartmentId>
<UserId xsi:nil="true" />
<Username />
<FullName />
<ConfirmDateTime xsi:nil="true" />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
</ArrayOfFlowDetailParameters>')
;
WITH XmlBreak as
(
SELECT x.v.query('.') TheXml,
x.v.value('(DepartmentId/text())[1]', 'int') DepartmentId,
x.v.value('(Status/text())[1]', 'varchar(50)') Status
FROM @table t
CROSS APPLY XmlCol.nodes ('/ArrayOfFlowDetailParameters/FlowDetailParameters') x(v)
)
SELECT *
FROM XmlBreak
WHERE DepartmentId = 23 and Status = 'Pending'
您可以直接在 XQuery 中将搜索条件应用于子节点:
declare @t table (XData xml);
declare @StatusValue varchar(50) = 'Pending',
@DepartmentId int = 23;
insert into @t (XData)
values (
N'<ArrayOfFlowDetailParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<FlowDetailParameters>
<DepartmentId>23</DepartmentId>
<UserId />
<Username />
<FullName />
<ConfirmDateTime />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>22</DepartmentId>
<UserId />
<Username />
<FullName />
<ConfirmDateTime />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>7</DepartmentId>
<UserId />
<Username />
<FullName />
<ConfirmDateTime />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
<FlowDetailParameters>
<DepartmentId>18</DepartmentId>
<UserId />
<Username />
<FullName />
<ConfirmDateTime />
<Comment />
<Status>Pending</Status>
<AttachmentId />
</FlowDetailParameters>
</ArrayOfFlowDetailParameters>');
select a.c.query('.')
from @t t
cross apply t.XData.nodes('/ArrayOfFlowDetailParameters/FlowDetailParameters[
./DepartmentId[1]/text() = sql:variable("@DepartmentId")
and ./Status[1]/text() = sql:variable("@StatusValue")
]') a(c);
此外,由于您可能需要它,我还提供了一个示例来说明如何对此类查询进行参数化。