如何在 sql 查询中解析多个命名空间 xml

How to parse multiple namespaces xml in sql query

我有一个 table,其中包含一个 XML 列,我正在尝试从 XML 数据中获取某些列。这些列位于 PositionRoles 标记下,该标记是 has INSERT 语句的一部分。不幸的是,我得到了 NULL 个值。

这是我使用的 XML 示例:

<request-broker-message version="1.0">
    <request class="UPDATE_ORGANISATION_HIERARCHY" culture="tr-TR">
        <parameter name="OrgHierarchyDatasets_schema">
            (here is not important...)
        </parameter>
        <parameter name="OrgHierarchyDatasets_diffgram">
            <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
                <NewDataSet>
                    <PositionRoles diffgr:id="PositionRoles1" msdata:rowOrder="0" diffgr:hasChanges="inserted">
                        <POSTN_ID>0000-0000H1-POS</POSTN_ID>
                        <ROLE_ID>0000-00002B-ROL</ROLE_ID>
                        <STATUS>1</STATUS>
                    </PositionRoles>
                </NewDataSet>
            </diffgr:diffgram>
        </parameter>
        <parameter name="ExistNodeCheck" type="System.Boolean">True</parameter>
    </request>
</request-broker-message>

我的尝试:

;WITH XMLNAMESPACES('urn:schemas-microsoft-com:xml-diffgram-v1' AS diffgr,
                    'inserted' AS hasChanges)

INSERT INTO TMP_ORGANIZATION_HIERARCHY_LOGS_TABLE(POSITION_ID, OPERATION, ROLE_ID, PACKET_OWNER, RESPONSE_TIME)
SELECT 
* 
FROM TMP_PACKET_LOG_TABLE (NOLOCK)
WHERE 
RESPONSE_PACKET.value('(/request-broker-message/request/parameter[@name="OrgHierarchyDatasets_diffgram"]//NewDataSet/hasChanges:PositionRoles/hasChanges:STATUS)[1]', 'varchar(1)') = '1'

不确定您所追求的具体价值是什么,但这应该足以让您到达那里。您需要在 WITH 中放置适当的名称空间(; 开头,语句以 1 结尾),然后在相关前缀具有相关命名空间名称的节点(例如 diffgr: 对应 diffgram):

DECLARE @XML xml =
'<request-broker-message version="1.0">
    <request class="UPDATE_ORGANISATION_HIERARCHY" culture="tr-TR">
        <parameter name="OrgHierarchyDatasets_schema">
            (here is not important...)
        </parameter>
        <parameter name="OrgHierarchyDatasets_diffgram">
            <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
                <NewDataSet>
                    <PositionRoles diffgr:id="PositionRoles1" msdata:rowOrder="0" diffgr:hasChanges="inserted">
                        <POSTN_ID>0000-0000H1-POS</POSTN_ID>
                        <ROLE_ID>0000-00002B-ROL</ROLE_ID>
                        <STATUS>1</STATUS>
                    </PositionRoles>
                </NewDataSet>
            </diffgr:diffgram>
        </parameter>
        <parameter name="ExistNodeCheck" type="System.Boolean">True</parameter>
    </request>
</request-broker-message>';

WITH XMLNAMESPACES ('urn:schemas-microsoft-com:xml-diffgram-v1' AS diffgr,
                    'urn:schemas-microsoft-com:xml-msdata' AS msdata)
SELECT dg.NDS.value('(PositionRoles/@diffgr:id)[1]','varchar(30)') AS id,
       dg.NDS.value('(PositionRoles/@msdata:rowOrder)[1]','int') AS rowOrder,
       dg.NDS.value('(PositionRoles/POSTN_ID/text())[1]','varchar(30)') AS POSTN_ID
FROM (VALUES(@XML))V(X)
     CROSS APPLY V.X.nodes('request-broker-message/request/parameter/diffgr:diffgram/NewDataSet') dg(NDS);

我还删除了 NOLOCK 命中,因为我怀疑它被滥用了:Bad habits : Putting NOLOCK everywhere