Shredding XML into SQLServer2005 tables

  • I need to shred an XML file into database tables. I can extract the Staff Details, but I need to load the Absences into a seperate table, linked with NI number so that I can add to it from a different source and then re-extract. Everything I've read suggests the select should do the job, but I can't seem to get the NINumber correct, I either get the same one for all four records, or null. Any ideas?

    DECLARE @iDoc int

    declare @XML as XML --varchar(max)

    declare @file as varchar(100)

    DECLARE @doc xml

    SET @doc ='

    &ltMessage xmlns:msxsl="urn:schemas-microsoft-com:xslt"&gt

    &ltSchoolWorkforceMembers&gt

    &ltSchoolWorkforceMember&gt

    &ltStaffDetails&gt

    &ltTeacherNumber&gt1111111&lt/TeacherNumber&gt

    &ltStaffMemberName&gt

    &ltPersonFamilyName&gtTEST1&lt/PersonFamilyName&gt

    &ltGivenNames&gt

    &ltGivenName&gt

    &ltPersonGivenName&gtName1&lt/PersonGivenName&gt

    &lt/GivenName&gt

    &ltGivenName&gt

    &ltPersonGivenName&gtName2&lt/PersonGivenName&gt

    &lt/GivenName&gt

    &lt/GivenNames&gt

    &lt/StaffMemberName&gt

    &ltNINumber&gtYY111111YY&lt/NINumber&gt

    &ltGenderCurrent&gt1&lt/GenderCurrent&gt

    &ltPersonBirthDate&gt1900-01-01&lt/PersonBirthDate&gt

    &ltEthnicity&gtUNK&lt/Ethnicity&gt

    &ltDisability&gtNOBT&lt/Disability&gt

    &ltQTStatus&gtYes&lt/QTStatus&gt

    &ltHLTAStatus&gtNo&lt/HLTAStatus&gt

    &ltAbsentOnCensusDay&gtN&lt/AbsentOnCensusDay&gt

    &lt/StaffDetails&gt

    &ltAbsences&gt

    &ltAbsence&gt

    &ltFirstDayOfAbsence&gt2008-11-07&lt/FirstDayOfAbsence&gt

    &ltLastDayOfAbsence&gt2008-11-07&lt/LastDayOfAbsence&gt

    &ltWorkingDaysLost&gt0.5&lt/WorkingDaysLost&gt

    &ltAbsenceCategory&gtTRN&lt/AbsenceCategory&gt

    &ltEstab&gt4408&lt/Estab&gt

    &lt/Absence&gt

    &ltAbsence&gt

    &ltFirstDayOfAbsence&gt2008-11-14&lt/FirstDayOfAbsence&gt

    &ltLastDayOfAbsence&gt2008-11-14&lt/LastDayOfAbsence&gt

    &ltWorkingDaysLost&gt0.5&lt/WorkingDaysLost&gt

    &ltAbsenceCategory&gtTRN&lt/AbsenceCategory&gt

    &ltEstab&gt4408&lt/Estab&gt

    &lt/Absence&gt

    &lt/Absences&gt

    &lt/SchoolWorkforceMember&gt

    &ltSchoolWorkforceMember&gt

    &ltStaffDetails&gt

    &ltTeacherNumber&gt2222222&lt/TeacherNumber&gt

    &ltStaffMemberName&gt

    &ltPersonFamilyName&gtTEST2&lt/PersonFamilyName&gt

    &ltGivenNames&gt

    &ltGivenName&gt

    &ltPersonGivenName&gtName1&lt/PersonGivenName&gt

    &lt/GivenName&gt

    &ltGivenName&gt

    &ltPersonGivenName&gtName2&lt/PersonGivenName&gt

    &lt/GivenName&gt

    &lt/GivenNames&gt

    &lt/StaffMemberName&gt

    &ltNINumber&gtXX123456XX&lt/NINumber&gt

    &ltGenderCurrent&gt1&lt/GenderCurrent&gt

    &ltPersonBirthDate&gt1901-01-01&lt/PersonBirthDate&gt

    &ltEthnicity&gtUNK&lt/Ethnicity&gt

    &ltDisability&gtNOBT&lt/Disability&gt

    &ltQTStatus&gtYes&lt/QTStatus&gt

    &ltHLTAStatus&gtNo&lt/HLTAStatus&gt

    &ltAbsentOnCensusDay&gtN&lt/AbsentOnCensusDay&gt

    &lt/StaffDetails&gt

    &ltAbsences&gt

    &ltAbsence&gt

    &ltFirstDayOfAbsence&gt2009-11-07&lt/FirstDayOfAbsence&gt

    &ltLastDayOfAbsence&gt2009-11-07&lt/LastDayOfAbsence&gt

    &ltWorkingDaysLost&gt0.5&lt/WorkingDaysLost&gt

    &ltAbsenceCategory&gtTRN&lt/AbsenceCategory&gt

    &ltEstab&gt4408&lt/Estab&gt

    &lt/Absence&gt

    &ltAbsence&gt

    &ltFirstDayOfAbsence&gt2009-11-14&lt/FirstDayOfAbsence&gt

    &ltLastDayOfAbsence&gt2009-11-14&lt/LastDayOfAbsence&gt

    &ltWorkingDaysLost&gt0.5&lt/WorkingDaysLost&gt

    &ltAbsenceCategory&gtTRN&lt/AbsenceCategory&gt

    &ltEstab&gt4408&lt/Estab&gt

    &lt/Absence&gt

    &lt/Absences&gt

    &lt/SchoolWorkforceMember&gt

    &lt/SchoolWorkforceMembers&gt

    &lt/Message&gt'

    -- Create an internal representation of the XML document.

    EXEC sp_xml_preparedocument @idoc OUTPUT, @doc

    SELECT *

    FROM OPENXML (@idoc,'/Message/SchoolWorkforceMembers/SchoolWorkforceMember/Absences/Absence', 2)

    WITH (NiNumber varchar (10) '/Message/SchoolWorkforceMembers/SchoolWorkforceMember/StaffDetails/NINumber' ,

    -- ** GIVES EVERYONE THE SAME NINUMBER

    -- WITH (NiNumber varchar (10) '/Message/SchoolWorkforceMembers/SchoolWorkforceMember/StaffDetails' , **JUST GETS ALL STAFF DETAILS IN A STRING

    FirstDayOfAbsence varchar(50) )

    --remove xml doc

    EXEC sp_xml_removedocument @iDoc

    Hope someone can help me with my first post! Thanks!

    :blush: Forgot to say that any solution has to work for a big file, not just the small extract shown here!

    :w00t: Latest update! From your excellent forums I devised this

    SELECT R.nref.value('../../NINumber[1]', 'varchar(10)') [NINumber],

    R.nref.value('.','varchar(10)') [FirstDayOfAbsence]

    FROM @doc.nodes('/Message/SchoolWorkforceMembers/SchoolWorkforceMember/Absences/Absence') AS R(nref)

    which (if I remove the StaffDetails layer - which seems superflous anyway, and I can probably edit the XML file before processing to do that) works! Except I can't then seem to get any more than the first field from then Absences node, and ultimately I need all of them.

    Any ideas for this angle?

  • Maybe this?

    SELECT m.value('(StaffDetails/NINumber)[1]','VARCHAR(10)') AS NINumber,

    b.value('FirstDayOfAbsence[1]','VARCHAR(10)') AS FirstDayOfAbsence,

    b.value('LastDayOfAbsence[1]','VARCHAR(10)') AS LastDayOfAbsence

    FROM @doc.nodes('/Message/SchoolWorkforceMembers/SchoolWorkforceMember') AS R(m)

    OUTER APPLY m.nodes('Absences/Absence') AS A(b)

    ____________________________________________________

    Deja View - The strange feeling that somewhere, sometime you've optimised this query before

    How to get the best help on a forum

    http://www.sqlservercentral.com/articles/Best+Practices/61537
  • 😀 Fantastic! Just the job. Thank you so much!!

  • Spoke too soon! Further examination gives another problem

    From this

    &ltSchoolWorkforceMember&gt

    &ltStaffDetails&gt

    &ltStaffMemberName&gt

    &ltPersonFamilyName&gtMOUSE&lt/PersonFamilyName&gt

    &ltGivenNames&gt

    &ltGivenName&gt

    &ltPersonGivenName&gtMickey&lt/PersonGivenName&gt

    &lt/GivenName&gt

    &lt/GivenNames&gt

    &lt/StaffMemberName&gt

    &ltNINumber&gtXX1111111XX&lt/NINumber&gt

    &ltGenderCurrent&gt2&lt/GenderCurrent&gt

    &ltPersonBirthDate&gt1901-01-01&lt/PersonBirthDate&gt

    &ltEthnicity&gtUNK&lt/Ethnicity&gt

    &ltDisability&gtNOBT&lt/Disability&gt

    &ltHLTAStatus&gtNo&lt/HLTAStatus&gt

    &ltAbsentOnCensusDay&gtY&lt/AbsentOnCensusDay&gt

    &lt/StaffDetails&gt

    &ltContractOrServiceGroup&gt

    &ltContractOrService&gt

    &ltContractType&gtPRM&lt/ContractType&gt

    &ltContractStart&gt2008-09-01&lt/ContractStart&gt

    &ltPost&gtUNA&lt/Post&gt

    &ltSchoolArrivalDate&gt1998-09-07&lt/SchoolArrivalDate&gt

    &ltOrigin&gtOTHEDU&lt/Origin&gt

    &ltLASchoolLevel&gtS&lt/LASchoolLevel&gt

    &ltEstab&gt9999&lt/Estab&gt

    &ltPostLevelDetails&gt

    &ltPayments&gt

    &ltScale&gtOT&lt/Scale&gt

    &ltRegionSpine&gtEW&lt/RegionSpine&gt

    &ltSalaryAmount&gt15825&lt/SalaryAmount&gt

    &ltSafeguardedSalary&gtfalse&lt/SafeguardedSalary&gt

    &lt/Payments&gt

    &ltHours&gt

    &ltHoursPerWeek&gt12.50&lt/HoursPerWeek&gt

    &ltFTEHours&gt37.00&lt/FTEHours&gt

    &ltWeeksPerYear&gt48&lt/WeeksPerYear&gt

    &lt/Hours&gt

    &lt/PostLevelDetails&gt

    &ltRoles&gt

    &ltRole&gt

    &ltRoleIdentifier&gtTASS&lt/RoleIdentifier&gt

    &lt/Role&gt

    &lt/Roles&gt

    &lt/ContractOrService&gt

    &ltContractOrService&gt

    &ltContractType&gtTMP&lt/ContractType&gt

    &ltContractStart&gt2008-09-01&lt/ContractStart&gt

    &ltPost&gtUNA&lt/Post&gt

    &ltSchoolArrivalDate&gt1998-09-07&lt/SchoolArrivalDate&gt

    &ltOrigin&gtOTHEDU&lt/Origin&gt

    &ltLASchoolLevel&gtS&lt/LASchoolLevel&gt

    &ltEstab&gt9999&lt/Estab&gt

    &ltPostLevelDetails&gt

    &ltPayments&gt

    &ltScale&gtOT&lt/Scale&gt

    &ltRegionSpine&gtEW&lt/RegionSpine&gt

    &ltSalaryAmount&gt15825&lt/SalaryAmount&gt

    &ltSafeguardedSalary&gtfalse&lt/SafeguardedSalary&gt

    &lt/Payments&gt

    &ltHours&gt

    &ltHoursPerWeek&gt3.50&lt/HoursPerWeek&gt

    &ltFTEHours&gt37.00&lt/FTEHours&gt

    &ltWeeksPerYear&gt48&lt/WeeksPerYear&gt

    &lt/Hours&gt

    &lt/PostLevelDetails&gt

    &ltRoles&gt

    &ltRole&gt

    &ltRoleIdentifier&gtTASS&lt/RoleIdentifier&gt

    &lt/Role&gt

    &lt/Roles&gt

    &lt/ContractOrService&gt

    &ltContractOrService&gt

    &ltContractType&gtFXT&lt/ContractType&gt

    &ltContractStart&gt2008-11-03&lt/ContractStart&gt

    &ltContractEnd&gt2008-12-31&lt/ContractEnd&gt

    &ltPost&gtUNA&lt/Post&gt

    &ltSchoolArrivalDate&gt1998-09-07&lt/SchoolArrivalDate&gt

    &ltDestinationCode&gtLEAPRM&lt/DestinationCode&gt

    &ltOrigin&gtOTHEDU&lt/Origin&gt

    &ltLASchoolLevel&gtS&lt/LASchoolLevel&gt

    &ltEstab&gt9999&lt/Estab&gt

    &ltPostLevelDetails&gt

    &ltHours&gt

    &ltHoursPerWeek&gt2.00&lt/HoursPerWeek&gt

    &ltFTEHours&gt37.00&lt/FTEHours&gt

    &ltWeeksPerYear&gt48&lt/WeeksPerYear&gt

    &lt/Hours&gt

    &lt/PostLevelDetails&gt

    &ltRoles&gt

    &ltRole&gt

    &ltRoleIdentifier&gtTASS&lt/RoleIdentifier&gt

    &lt/Role&gt

    &lt/Roles&gt

    &lt/ContractOrService&gt

    &lt/ContractOrServiceGroup&gt

    &lt/SchoolWorkforceMember&gt

    I need to get the NINumber, ContractStart and hours out in nice neat rows, like this

    XX111111XX 2008-09-01 12.50

    XX111111XX 2008-09-01 3.50

    XX111111XX 2008-11-03 2.00

    Any ideas? I've tried adapting the previous answer, but either get multiplied rows or the same ContractStart for all three.

    Thanks in anticipation!

  • SELECT m.value('(StaffDetails/NINumber)[1]','VARCHAR(10)') AS NINumber,

    b.value('ContractStart[1]','VARCHAR(10)') AS ContractStart,

    b.value('(PostLevelDetails/Hours/HoursPerWeek)[1]','DECIMAL(10,2)') AS Hours

    FROM @doc.nodes('/SchoolWorkforceMember') AS R(m)

    OUTER APPLY m.nodes('ContractOrServiceGroup/ContractOrService') AS A(b)

    ____________________________________________________

    Deja View - The strange feeling that somewhere, sometime you've optimised this query before

    How to get the best help on a forum

    http://www.sqlservercentral.com/articles/Best+Practices/61537
  • Thanks, exactly what I needed!

Viewing 6 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic. Login to reply