使用 T-SQL 解析 XML 数据

Parsing XML Data using T-SQL

我正在尝试使用 SQL Server 2019 解析 XML 数据。

我有以下数据集:

<?xml version='1.0' encoding='UTF-8'?>
<wd:Report_Data xmlns:wd="urn:com.test.report/Reported_Time_Blocks_for_a_Worker_s__-_Test_Worked_Hours_-_Copy">
    <wd:Report_Entry>
        <wd:Worker_group>
            <wd:Employee_ID>111111</wd:Employee_ID>
            <wd:Legal_Name_-_First_Name>TestFirstName</wd:Legal_Name_-_First_Name>
            <wd:Legal_Name_-_Last_Name>TestLastName</wd:Legal_Name_-_Last_Name>
        </wd:Worker_group>
        <wd:Employee_Type wd:Descriptor="Property">
            <wd:ID wd:type="WID">xxxxxxxxxxxxxxxxxxxxxxxxxxx</wd:ID>
            <wd:ID wd:type="Employee_Type_ID">Regular</wd:ID>
        </wd:Employee_Type>
        <wd:Pay_Rate_Type wd:Descriptor="Salary">
            <wd:ID wd:type="WID">xxxxxxxxxxxxxxxxxxxxxxxxxxx</wd:ID>
            <wd:ID wd:type="Pay_Rate_Type_ID">Salary</wd:ID>
        </wd:Pay_Rate_Type>
        <wd:Pay_Rate>0</wd:Pay_Rate>
        <wd:Home_Cost_Center wd:Descriptor="CC0001 Test Property">
            <wd:ID wd:type="WID">xxxxxxxxxxxxxxxxxxxxxxxxxx</wd:ID>
            <wd:ID wd:type="Organization_Reference_ID">CC0001</wd:ID>
            <wd:ID wd:type="Cost_Center_Reference_ID">CC0001</wd:ID>
        </wd:Home_Cost_Center>
        <wd:Home_Subarea wd:Descriptor="HS001 Test Home">
            <wd:ID wd:type="WID">xxxxxxxxxxxxxxxxxxxxxxxxxx</wd:ID>
            <wd:ID wd:type="Organization_Reference_ID">HS001</wd:ID>
            <wd:ID wd:type="Custom_Organization_Reference_ID">HS001</wd:ID>
        </wd:Home_Subarea>
        <wd:Home_Job_Profile wd:Descriptor="Test Job Title">
            <wd:ID wd:type="WID">6db2e1cea51601ac7fdd4d733e001646</wd:ID>
            <wd:ID wd:type="Job_Profile_ID">100000001</wd:ID>
        </wd:Home_Job_Profile>
        <wd:Reported_Date>2022-04-11-07:00</wd:Reported_Date>
        <wd:Reported_Quantity>8</wd:Reported_Quantity>
        <wd:Time_Entry_Code wd:Descriptor="Worked Time (Hours Only)">
            <wd:ID wd:type="WID">xxxxxxxxxxxxxxxxxxxxxxxxxx</wd:ID>
            <wd:ID wd:type="Time_Code_Reference_ID">Worked_Time_Hours_Only_Time_Code</wd:ID>
        </wd:Time_Entry_Code>
        <wd:Calculation_Tags wd:Descriptor="Regular">
            <wd:ID wd:type="WID">xxxxxxxxxxxxxxxxxxxxxxxxxx</wd:ID>
            <wd:ID wd:type="Time_Calculation_Tag_ID">Regular</wd:ID>
        </wd:Calculation_Tags>
    </wd:Report_Entry>

我知道如何获取一些数据,但我不知道如何使用多个行组。

我有这个查询可以提取 Employee_ID、Legal_Name_-First_Name 和 Legal_Name-_Last_Name ,但我不知道如何用它来拉 Employee_Type、Pay_Rate_Type 等:

DECLARE @XML XML
    SET @XML = ( SELECT XMLData FROM #XML )

DECLARE @XML XML
    SET @XML = ( SELECT XMLData FROM #XML )

;WITH XMLNAMESPACES( 'urn:com.test.report/Reported_Time_Blocks_for_a_Worker_s__-_Test_Worked_Hours_-_Copy' AS wd )
SELECT  EmployeeId = Data.Col.value( 'wd:Employee_ID[1]', 'VARCHAR(12)' ),
        FirstName = Data.Col.value( 'wd:Legal_Name_-_First_Name[1]', 'VARCHAR(100)' ),
        LastName = Data.Col.value( 'wd:Legal_Name_-_Last_Name[1]', 'VARCHAR(100)' )
    --INTO #EmployeeInformation
    FROM @XML.nodes( 'wd:Report_Data/wd:Report_Entry/wd:Worker_group' ) Data( Col )

我实际上是在尝试从上面的 XML 中提取以下数据:

Employee_ID Legal_Name_-_First_Name Legal_Name_-_Last_Name Employee_Type_ID Pay_Rate_Type_ID Pay_Rate Cost_Center_Reference_ID Reported_Date Reported_Quantity Home_Job_Profile_Descriptor
111111 TestFirstName TestLastName Regular Salary 0 CC0001 2022-04-11-07:00 8 Test Job Title

请尝试以下解决方案。

您可能需要调整数据类型。

SQL

DECLARE @xml XML =
N'<wd:Report_Data xmlns:wd="urn:com.test.report/Reported_Time_Blocks_for_a_Worker_s__-_Test_Worked_Hours_-_Copy">
    <wd:Report_Entry>
        <wd:Worker_group>
            <wd:Employee_ID>111111</wd:Employee_ID>
            <wd:Legal_Name_-_First_Name>TestFirstName</wd:Legal_Name_-_First_Name>
            <wd:Legal_Name_-_Last_Name>TestLastName</wd:Legal_Name_-_Last_Name>
        </wd:Worker_group>
        <wd:Employee_Type wd:Descriptor="Property">
            <wd:ID wd:type="WID">xxxxxxxxxxxxxxxxxxxxxxxxxxx</wd:ID>
            <wd:ID wd:type="Employee_Type_ID">Regular</wd:ID>
        </wd:Employee_Type>
        <wd:Pay_Rate_Type wd:Descriptor="Salary">
            <wd:ID wd:type="WID">xxxxxxxxxxxxxxxxxxxxxxxxxxx</wd:ID>
            <wd:ID wd:type="Pay_Rate_Type_ID">Salary</wd:ID>
        </wd:Pay_Rate_Type>
        <wd:Pay_Rate>0</wd:Pay_Rate>
        <wd:Home_Cost_Center wd:Descriptor="CC0001 Test Property">
            <wd:ID wd:type="WID">xxxxxxxxxxxxxxxxxxxxxxxxxx</wd:ID>
            <wd:ID wd:type="Organization_Reference_ID">CC0001</wd:ID>
            <wd:ID wd:type="Cost_Center_Reference_ID">CC0001</wd:ID>
        </wd:Home_Cost_Center>
        <wd:Home_Subarea wd:Descriptor="HS001 Test Home">
            <wd:ID wd:type="WID">xxxxxxxxxxxxxxxxxxxxxxxxxx</wd:ID>
            <wd:ID wd:type="Organization_Reference_ID">HS001</wd:ID>
            <wd:ID wd:type="Custom_Organization_Reference_ID">HS001</wd:ID>
        </wd:Home_Subarea>
        <wd:Home_Job_Profile wd:Descriptor="Test Job Title">
            <wd:ID wd:type="WID">6db2e1cea51601ac7fdd4d733e001646</wd:ID>
            <wd:ID wd:type="Job_Profile_ID">100000001</wd:ID>
        </wd:Home_Job_Profile>
        <wd:Reported_Date>2022-04-11-07:00</wd:Reported_Date>
        <wd:Reported_Quantity>8</wd:Reported_Quantity>
        <wd:Time_Entry_Code wd:Descriptor="Worked Time (Hours Only)">
            <wd:ID wd:type="WID">xxxxxxxxxxxxxxxxxxxxxxxxxx</wd:ID>
            <wd:ID wd:type="Time_Code_Reference_ID">Worked_Time_Hours_Only_Time_Code</wd:ID>
        </wd:Time_Entry_Code>
        <wd:Calculation_Tags wd:Descriptor="Regular">
            <wd:ID wd:type="WID">xxxxxxxxxxxxxxxxxxxxxxxxxx</wd:ID>
            <wd:ID wd:type="Time_Calculation_Tag_ID">Regular</wd:ID>
        </wd:Calculation_Tags>
    </wd:Report_Entry>
</wd:Report_Data>';

;WITH XMLNAMESPACES(DEFAULT 'urn:com.test.report/Reported_Time_Blocks_for_a_Worker_s__-_Test_Worked_Hours_-_Copy')
SELECT EmployeeId = c.value('(Worker_group/Employee_ID/text())[1]', 'VARCHAR(12)' )
    , FirstName = c.value('(Worker_group/Legal_Name_-_First_Name/text())[1]', 'VARCHAR(100)' )
    , LastName = c.value('(Worker_group/Legal_Name_-_Last_Name/text())[1]', 'VARCHAR(100)' )
    , Employee_Type_ID = c.value('(Employee_Type/ID[@*:type="Employee_Type_ID"]/text())[1]', 'VARCHAR(100)' )
    , Pay_Rate_Type_ID = c.value('(Pay_Rate_Type/ID[@*:type="Pay_Rate_Type_ID"]/text())[1]', 'VARCHAR(100)' )
    , Pay_Rate = c.value('(Pay_Rate/text())[1]', 'VARCHAR(100)' )
    , Cost_Center_Reference_ID = c.value('(Home_Cost_Center/ID[@*:type="Cost_Center_Reference_ID"]/text())[1]', 'VARCHAR(100)' )
    , Reported_Date = c.value('(Reported_Date/text())[1]', 'VARCHAR(100)' )
    , Reported_Quantity = c.value('(Reported_Quantity/text())[1]', 'VARCHAR(100)' )
    , Home_Job_Profile_Descriptor = c.value('(Home_Job_Profile/@*:Descriptor)[1]', 'VARCHAR(100)' )
FROM @XML.nodes('/Report_Data/Report_Entry') AS t(c);

输出

+------------+---------------+--------------+------------------+------------------+----------+--------------------------+------------------+-------------------+-----------------------------+
| EmployeeId |   FirstName   |   LastName   | Employee_Type_ID | Pay_Rate_Type_ID | Pay_Rate | Cost_Center_Reference_ID |  Reported_Date   | Reported_Quantity | Home_Job_Profile_Descriptor |
+------------+---------------+--------------+------------------+------------------+----------+--------------------------+------------------+-------------------+-----------------------------+
|     111111 | TestFirstName | TestLastName | Regular          | Salary           |        0 | CC0001                   | 2022-04-11-07:00 |                 8 | Test Job Title              |
+------------+---------------+--------------+------------------+------------------+----------+--------------------------+------------------+-------------------+-----------------------------+