问题
I have a big size XML document (50.000-100,000) that needs to be parsed on Azure SQL that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<covid-19 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://covid-19.iss.it/XMLSchema/0.1/">
<pazienti>
<paziente>
<codiceRegionalePaziente>0123456789</codiceRegionalePaziente>
<codiceFiscale/>
<nome>nomeBulk01</nome>
<cognome>cognomeBulk01</cognome>
<dataNascita>1989-12-31</dataNascita>
<sesso>F</sesso>
<nazionalita>380</nazionalita>
<domicilioIndirizzo/>
<domicilioCap>00019</domicilioCap>
<domicilioComune>058104</domicilioComune>
<domicilioProvincia>RM</domicilioProvincia>
<residenzaIndirizzo/>
<residenzaCap/>
<residenzaComune/>
<residenzaProvincia/>
<luogoEsposizione>cinema</luogoEsposizione>
<luogoEsposizioneComune>058047</luogoEsposizioneComune>
<operatoreSanitario>1</operatoreSanitario>
<casoIsolato>9</casoIsolato>
<casoCollegato/>
<codiceTampone>kkk12345</codiceTampone>
<dataPrelievo>2020-03-01</dataPrelievo>
<codLaboratorioAnalisi>999</codLaboratorioAnalisi>
<sequenzaGenoma>9</sequenzaGenoma>
<sequenzaInviata>0</sequenzaInviata>
<dataInizioSintomi>2020-03-01</dataInizioSintomi>
<codRegione>99</codRegione>
<patologieCroniche>9</patologieCroniche>
<tumoriAttivi/>
<diabeteMellito/>
<malattieCardiovascolari/>
<hiv/>
<malattieRespiratorieCroniche/>
<malattieRenali/>
<altreMalattieMetaboliche/>
<obesitaBmi30e40/>
<obesitaBmiOltre40/>
<malattieEpatiche/>
<malattieCronicheNeurologiche/>
<altrePatologie/>
<altrePatologieDescrizione/>
<note>test caricamento massivo da file xml</note>
<collocazioni>
<collocazione>
<dataCollocazione>2020-03-01</dataCollocazione>
<collocazioneTipo>Ospedale</collocazioneTipo>
<ospedaleNSIS>99999999</ospedaleNSIS>
<ospedaleReparto>Pneumologia</ospedaleReparto>
</collocazione>
</collocazioni>
<statiClinici>
<statoClinico>
<tipoStatoClinico>Asintomatico</tipoStatoClinico>
<dataStatoClinico>2020-03-01</dataStatoClinico>
<terapiaInCorso>0</terapiaInCorso>
<terapiaDescrizione/>
<intubato>0</intubato>
</statoClinico>
<statoClinico>
<tipoStatoClinico>Lieve</tipoStatoClinico>
<dataStatoClinico>2020-03-12</dataStatoClinico>
<terapiaInCorso>0</terapiaInCorso>
<terapiaDescrizione/>
<intubato>0</intubato>
</statoClinico>
<statoClinico>
<tipoStatoClinico>Critico</tipoStatoClinico>
<dataStatoClinico>2020-03-18</dataStatoClinico>
<terapiaInCorso>0</terapiaInCorso>
<terapiaDescrizione/>
<intubato>1</intubato>
</statoClinico>
</statiClinici>
</paziente>
<paziente>
<codiceRegionalePaziente>AABB1234567890</codiceRegionalePaziente>
<codiceFiscale>AAABBB00C11D222E</codiceFiscale>
<nome>nomeBulk02</nome>
<cognome>cognomeBulk02</cognome>
<dataNascita>2000-01-31</dataNascita>
<sesso>M</sesso>
<nazionalita>380</nazionalita>
<domicilioIndirizzo>Via del domicilio</domicilioIndirizzo>
<domicilioCap>00100</domicilioCap>
<domicilioComune>058091</domicilioComune>
<domicilioProvincia>RM</domicilioProvincia>
<residenzaIndirizzo/>
<residenzaCap/>
<residenzaComune/>
<residenzaProvincia/>
<luogoEsposizione>centro commerciale</luogoEsposizione>
<luogoEsposizioneComune>058091</luogoEsposizioneComune>
<operatoreSanitario>0</operatoreSanitario>
<casoIsolato>1</casoIsolato>
<casoCollegato/>
<codiceTampone>00AABB-CC</codiceTampone>
<dataPrelievo>2020-02-29</dataPrelievo>
<codLaboratorioAnalisi>999</codLaboratorioAnalisi>
<sequenzaGenoma>1</sequenzaGenoma>
<sequenzaInviata>0</sequenzaInviata>
<dataInizioSintomi>2020-02-29</dataInizioSintomi>
<codRegione>99</codRegione>
<patologieCroniche>1</patologieCroniche>
<tumoriAttivi>0</tumoriAttivi>
<diabeteMellito>0</diabeteMellito>
<malattieCardiovascolari>1</malattieCardiovascolari>
<hiv>0</hiv>
<malattieRespiratorieCroniche>1</malattieRespiratorieCroniche>
<malattieRenali>0</malattieRenali>
<altreMalattieMetaboliche>0</altreMalattieMetaboliche>
<obesitaBmi30e40>0</obesitaBmi30e40>
<obesitaBmiOltre40>0</obesitaBmiOltre40>
<malattieEpatiche>0</malattieEpatiche>
<malattieCronicheNeurologiche>0</malattieCronicheNeurologiche>
<altrePatologie>1</altrePatologie>
<altrePatologieDescrizione>descrizione altra patologia cronica</altrePatologieDescrizione>
<note>test caricamento massivo da file xml</note>
<collocazioni>
<collocazione>
<dataCollocazione>2020-03-01</dataCollocazione>
<collocazioneTipo>Domicilio</collocazioneTipo>
<ospedaleNSIS/>
<ospedaleReparto/>
</collocazione>
<collocazione>
<dataCollocazione>2020-03-05</dataCollocazione>
<collocazioneTipo>Ospedale</collocazioneTipo>
<ospedaleNSIS>99999999</ospedaleNSIS>
<ospedaleReparto>Malattie infettive e tropicali</ospedaleReparto>
</collocazione>
</collocazioni>
<statiClinici>
<statoClinico>
<tipoStatoClinico>Pauci-sintomatico</tipoStatoClinico>
<dataStatoClinico>2020-02-29</dataStatoClinico>
<terapiaInCorso>0</terapiaInCorso>
<terapiaDescrizione/>
<intubato>0</intubato>
</statoClinico>
<statoClinico>
<tipoStatoClinico>Severo</tipoStatoClinico>
<dataStatoClinico>2020-03-17</dataStatoClinico>
<terapiaInCorso>1</terapiaInCorso>
<terapiaDescrizione>descrizione della terapia in corso</terapiaDescrizione>
<intubato>0</intubato>
</statoClinico>
</statiClinici>
</paziente>
<paziente>
<codiceRegionalePaziente>9999999</codiceRegionalePaziente>
<codiceFiscale/>
<nome>nomeBulk03</nome>
<cognome>cognomeBulk03</cognome>
<dataNascita>2000-01-31</dataNascita>
<sesso>M</sesso>
<nazionalita>380</nazionalita>
<domicilioIndirizzo>Via del domicilio</domicilioIndirizzo>
<domicilioCap>00100</domicilioCap>
<domicilioComune>058091</domicilioComune>
<domicilioProvincia>RM</domicilioProvincia>
<residenzaIndirizzo/>
<residenzaCap/>
<residenzaComune/>
<residenzaProvincia/>
<luogoEsposizione>centro commerciale</luogoEsposizione>
<luogoEsposizioneComune>058091</luogoEsposizioneComune>
<operatoreSanitario>0</operatoreSanitario>
<casoIsolato>1</casoIsolato>
<casoCollegato/>
<codiceTampone>00AABB-CC</codiceTampone>
<dataPrelievo>2020-02-29</dataPrelievo>
<codLaboratorioAnalisi>999</codLaboratorioAnalisi>
<sequenzaGenoma>1</sequenzaGenoma>
<sequenzaInviata>0</sequenzaInviata>
<dataInizioSintomi>2020-02-29</dataInizioSintomi>
<codRegione>99</codRegione>
<patologieCroniche>1</patologieCroniche>
<tumoriAttivi>0</tumoriAttivi>
<diabeteMellito>0</diabeteMellito>
<malattieCardiovascolari>1</malattieCardiovascolari>
<hiv>0</hiv>
<malattieRespiratorieCroniche>1</malattieRespiratorieCroniche>
<malattieRenali>0</malattieRenali>
<altreMalattieMetaboliche>0</altreMalattieMetaboliche>
<obesitaBmi30e40>0</obesitaBmi30e40>
<obesitaBmiOltre40>0</obesitaBmiOltre40>
<malattieEpatiche>0</malattieEpatiche>
<malattieCronicheNeurologiche>0</malattieCronicheNeurologiche>
<altrePatologie>1</altrePatologie>
<altrePatologieDescrizione>descrizione altra patologia cronica</altrePatologieDescrizione>
<note>test caricamento massivo da file xml</note>
<collocazioni>
</collocazioni>
<statiClinici>
</statiClinici>
</paziente>
</pazienti>
</covid-19>
I need to split it into 3 regular table type dataset (pazienti, collocazioni, statiClinici) and I use the following T-SQL code that works:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON
DECLARE @StartTime datetime = getdate()
-- Insert statements for procedure here
-- DROP temp tables
if object_id('tempdb..#xmlPazienti') is not null DROP TABLE #xmlPazienti;
if object_id('tempdb..#xmlCollocazioni') is not null DROP TABLE #xmlCollocazioni;
if object_id('tempdb..#xmlStatiClinici') is not null DROP TABLE #xmlStatiClinici;
-- pazienti --
CREATE TABLE #xmlPazienti
(
[patientId] [int] NULL
,[codiceFiscale] [varchar](16) NULL
,[nome] [nvarchar](255) NULL
,[cognome] [nvarchar](255) NULL
,[dataNascita] [datetime] NULL
,[sesso] [char](1) NULL
,[nazionalita] [smallint] NULL
,[domicilioInd] [varchar](255) NULL
,[domicilioCap] [varchar](10) NULL
,[domicilioCom] [varchar](255) NULL
,[domicilioProv] [varchar](255) NULL
,[residenzaInd] [varchar](255) NULL
,[residenzaCap] [varchar](10) NULL
,[residenzaCom] [varchar](255) NULL
,[residenzaProv] [varchar](255) NULL
,[luogoEsp] [nvarchar](500) NULL
,[luogoEspCom] [varchar](255) NULL
,[operatoreSanitario] [tinyint] NULL
,[casoIsolato] [tinyint] NULL
,[casoCollegato] [varchar](500) NULL
,[CodiceTampone] [varchar](255) NULL
,[dataPrelievo] [date] NULL
,[LaboratorioAnalisiId] [smallint] NULL
,[sequenzaGenoma] [tinyint] NULL
,[sequenzaInviata] [tinyint] NULL
,[DataInizioSintomi] [date] NULL
,[codRegione] [smallint] NULL
,[PatologieCroniche] [tinyint] NULL
,[TumoriAttivi] [tinyint] NULL
,[DiabeteMellito] [tinyint] NULL
,[MalattieCardiovascolari] [tinyint] NULL
,[HIV] [tinyint] NULL
,[MalattieRespiratorieCroniche] [tinyint] NULL
,[MalattieRenali] [tinyint] NULL
,[AltreMalattieMetaboliche] [tinyint] NULL
,[ObesitàBMI30e40] [tinyint] NULL
,[ObesitàBMIoltre40] [tinyint] NULL
,[MalattieEpatiche] [tinyint] NULL
,[MalattieCronicheNeurologiche] [tinyint] NULL
,[AltrePatologie] [tinyint] NULL
,[AltrePatologieDescrizione] [nvarchar](500) NULL
,[Note] [nvarchar](4000) NULL
,[patientID_reg] [nvarchar](50) NULL
,[flagBaseline] [int] NULL
)
-- pazienti --
-- collocazioni --
CREATE TABLE #xmlCollocazioni
(
dataRicovero date NULL
,collocazioneId int NULL
,idOspedale nvarchar(255) NULL
,CodReparto int NULL
,patientID int NULL
,patientID_reg nvarchar(50) NULL
,collocazioneTipo nvarchar(50) NULL
,ospedaleReparto nvarchar(255) NULL
);
-- collocazioni --
-- stati clinici --
CREATE TABLE #xmlStatiClinici
(
patientID int NULL
,statoClinicoId int NULL
,dataStatoClinico date NULL
,terapiaInCorso int NULL
,terapia nvarchar(1000) NULL
,Intubato int NULL
,patientID_reg nvarchar(50) NULL
,tipoStatoClinico nvarchar(50) NULL
);
-- stati clinici --
-- index on temp tables --
CREATE INDEX ixTmp_patient_patientId ON #xmlPazienti (patientId);
CREATE INDEX ixTmp_patient_patientID_reg ON #xmlPazienti (patientID_reg);
CREATE INDEX ixTmp_patient_codRegione ON #xmlPazienti (codRegione) INCLUDE (patientId);
CREATE INDEX ixTmp_patient_LaboratorioAnalisiId ON #xmlPazienti (LaboratorioAnalisiId);
CREATE INDEX ixTmp_ricovero_patientId ON #xmlCollocazioni (patientId);
CREATE INDEX ixTmp_ricovero_patientID_reg ON #xmlCollocazioni (patientID_reg);
CREATE INDEX ixTmp_ricovero_collocazioneID ON #xmlCollocazioni (collocazioneID);
CREATE INDEX ixTmp_ricovero_idOspedale ON #xmlCollocazioni (idOspedale);
CREATE INDEX ixTmp_ricovero_codReparto ON #xmlCollocazioni (codReparto);
CREATE INDEX ixTmp_monitoring_patientId ON #xmlStatiClinici (patientId);
CREATE INDEX ixTmp_monitoring_patientID_reg ON #xmlStatiClinici (patientID_reg);
CREATE INDEX ixTmp_monitoring_statoClinicoId ON #xmlStatiClinici (statoClinicoId);
-- index on temp tables --
DECLARE @StartTimeInsertPazienti datetime = getdate()
DECLARE @fId INT = 187
DECLARE @XML AS XML
SELECT @XML = XMLData FROM XMLbulkLoad WHERE Id = @fId
;WITH XMLNAMESPACES(DEFAULT 'http://covid-19.iss.it/XMLSchema/0.1/')
-- pazienti --
INSERT INTO #xmlPazienti WITH (TABLOCK) ([patientID_reg],[codiceFiscale],[cognome],[nome],[dataNascita],[sesso],[nazionalita],[domicilioInd],[domicilioCap],[domicilioCom],[domicilioProv],[residenzaInd],[residenzaCap],[residenzaCom],[residenzaProv],[luogoEsp],[luogoEspCom],[operatoreSanitario],[casoIsolato],[casoCollegato],[CodiceTampone],[dataPrelievo],[LaboratorioAnalisiId],[sequenzaGenoma],[sequenzaInviata],[DataInizioSintomi],[codRegione],[PatologieCroniche],[TumoriAttivi],[DiabeteMellito],[MalattieCardiovascolari],[HIV],[MalattieRespiratorieCroniche],[MalattieRenali],[AltreMalattieMetaboliche],[ObesitàBMI30e40],[ObesitàBMIoltre40],[MalattieEpatiche],[MalattieCronicheNeurologiche],[AltrePatologie],[AltrePatologieDescrizione],[Note])
SELECT ISNULL(paz.value('(codiceRegionalePaziente/text())[1]', 'nvarchar(50)'),NULL) AS [patientID_reg]
,ISNULL(paz.value('(codiceFiscale/text())[1]', 'varchar(16)'),NULL) AS [codiceFiscale]
,ISNULL(paz.value('(cognome/text())[1]', 'nvarchar(255)'),NULL) AS [cognome]
,ISNULL(paz.value('(nome/text())[1]', 'nvarchar(255)'),NULL) AS [nome]
,ISNULL(paz.value('(dataNascita/text())[1]', 'datetime'),NULL) AS [dataNascita]
,ISNULL(paz.value('(sesso/text())[1]', 'char(1)'),NULL) AS [sesso]
,ISNULL(paz.value('(nazionalita/text())[1]', 'smallint'),NULL) AS [nazionalita]
,ISNULL(paz.value('(domicilioIndirizzo/text())[1]', 'varchar(255)'),NULL) AS [domicilioInd]
,ISNULL(paz.value('(domicilioCap/text())[1]', 'varchar(10)'),NULL) AS [domicilioCap]
,ISNULL(paz.value('(domicilioComune/text())[1]', 'varchar(255)'),NULL) AS [domicilioCom]
,ISNULL(paz.value('(domicilioProvincia/text())[1]', 'varchar(255)'),NULL) AS [domicilioProv]
,ISNULL(paz.value('(residenzaIndirizzo/text())[1]', 'varchar(255)'),NULL) AS [residenzaInd]
,ISNULL(paz.value('(residenzaCap/text())[1]', 'varchar(10)'),NULL) AS [residenzaCap]
,ISNULL(paz.value('(residenzaComune/text())[1]', 'varchar(255)'),NULL) AS [residenzaCom]
,ISNULL(paz.value('(residenzaProvincia/text())[1]', 'varchar(255)'),NULL) AS [residenzaProv]
,ISNULL(paz.value('(luogoEsposizione/text())[1]', 'nvarchar(500)'),NULL) AS [luogoEsp]
,ISNULL(paz.value('(luogoEsposizioneComune/text())[1]', 'varchar(255)'),NULL) AS [luogoEspCom]
,ISNULL(paz.value('(operatoreSanitario/text())[1]', 'tinyint'),NULL) AS [operatoreSanitario]
,ISNULL(paz.value('(casoIsolato/text())[1]', 'tinyint'),NULL) AS [casoIsolato]
,ISNULL(paz.value('(casoCollegato/text())[1]', 'varchar(500)'),NULL) AS [casoCollegato]
,ISNULL(paz.value('(codiceTampone/text())[1]', 'varchar(255)'),NULL) AS [CodiceTampone]
,ISNULL(paz.value('(dataPrelievo/text())[1]', 'date'),NULL) AS [dataPrelievo]
,ISNULL(paz.value('(codLaboratorioAnalisi/text())[1]', 'smallint'),NULL) AS [LaboratorioAnalisiId]
,ISNULL(paz.value('(sequenzaGenoma/text())[1]', 'tinyint'),NULL) AS [sequenzaGenoma]
,ISNULL(paz.value('(sequenzaInviata/text())[1]', 'tinyint'),NULL) AS [sequenzaInviata]
,ISNULL(paz.value('(dataInizioSintomi/text())[1]', 'date'),NULL) AS [dataInizioSintomi]
,ISNULL(paz.value('(codRegione/text())[1]', 'smallint'),'') AS [codRegione]
,ISNULL(paz.value('(patologieCroniche/text())[1]', 'tinyint'),NULL) AS [patologieCroniche]
,ISNULL(paz.value('(tumoriAttivi/text())[1]', 'tinyint'),NULL) AS [tumoriAttivi]
,ISNULL(paz.value('(diabeteMellito/text())[1]', 'tinyint'),NULL) AS [diabeteMellito]
,ISNULL(paz.value('(malattieCardiovascolari/text())[1]', 'tinyint'),NULL) AS [malattieCardiovascolari]
,ISNULL(paz.value('(hiv/text())[1]', 'tinyint'),NULL) AS [hiv]
,ISNULL(paz.value('(malattieRespiratorieCroniche/text())[1]', 'tinyint'),NULL) AS [malattieRespiratorieCroniche]
,ISNULL(paz.value('(malattieRenali/text())[1]', 'tinyint'),NULL) AS [malattieRenali]
,ISNULL(paz.value('(altreMalattieMetaboliche/text())[1]', 'tinyint'),NULL) AS [altreMalattieMetaboliche]
,ISNULL(paz.value('(obesitaBmi30e40/text())[1]', 'tinyint'),NULL) AS [ObesitàBMI30e40]
,ISNULL(paz.value('(obesitaBmiOltre40/text())[1]', 'tinyint'),NULL) AS [ObesitàBMIoltre40]
,ISNULL(paz.value('(malattieEpatiche/text())[1]', 'tinyint'),NULL) AS [malattieEpatiche]
,ISNULL(paz.value('(malattieCronicheNeurologiche/text())[1]', 'tinyint'),NULL) AS [malattieCronicheNeurologiche]
,ISNULL(paz.value('(altrePatologie/text())[1]', 'tinyint'),NULL) AS [altrePatologie]
,ISNULL(paz.value('(altrePatologieDescrizione/text())[1]', 'nvarchar(500)'),NULL) AS [altrePatologieDescrizione]
,ISNULL(paz.value('(note/text())[1]', 'nvarchar(4000)'),NULL) AS [note]
FROM
@XML.nodes('covid-19/pazienti/paziente') AS A(paz)
--OPTION (OPTIMIZE FOR UNKNOWN)
--OPTION (RECOMPILE)
-- pazienti --
DECLARE @EndTimeInsertPazienti datetime = getdate()
SELECT DATEDIFF (SS ,@StartTimeInsertPazienti,@EndTimeInsertPazienti) AS PazientiInsertDuration
DECLARE @StartTimeInsertCollocazioni datetime = getdate()
-- collocazioni --
--SELECT @XML = XMLData FROM XMLbulkLoadDEV WHERE Id = @fID
--;WITH XMLNAMESPACES(DEFAULT 'http://covid-19.iss.it/XMLSchema/0.1/')
INSERT INTO #xmlCollocazioni WITH (TABLOCK) (patientID_reg, dataRicovero, collocazioneTipo, idOspedale, ospedaleReparto)
SELECT COALESCE(paz.value('(codiceRegionalePaziente/text())[1]', 'nvarchar(50)'),NULL) AS [patientID_reg]
,COALESCE(coll.value('(dataCollocazione/text())[1]', 'date'),NULL) AS [dataRicovero]
,COALESCE(coll.value('(collocazioneTipo/text())[1]', 'nvarchar(50)'),NULL) AS [collocazioneTipo]
,COALESCE(coll.value('(ospedaleNSIS/text())[1]', 'nvarchar(255)'),NULL) AS [idOspedale]
,COALESCE(coll.value('(ospedaleReparto/text())[1]', 'nvarchar(255)'),NULL) AS [ospedaleReparto]
FROM
@XML.nodes('covid-19/pazienti/paziente') AS A(paz)
OUTER APPLY
paz.nodes('collocazioni/collocazione') B(coll)
--OPTION (OPTIMIZE FOR UNKNOWN)
--OPTION (RECOMPILE)
-- collocazioni --
DECLARE @EndTimeInsertCollocazioni datetime = getdate()
SELECT DATEDIFF (SS ,@StartTimeInsertCollocazioni,@EndTimeInsertCollocazioni) AS CollocazioniInsertDuration
DECLARE @StarTimeInsertStatiClinici datetime = getdate()
-- stati clinici --
--SELECT @XML = XMLData FROM XMLbulkLoadDEV WHERE Id = @fID
--;WITH XMLNAMESPACES(DEFAULT 'http://covid-19.iss.it/XMLSchema/0.1/')
INSERT INTO #xmlStatiClinici WITH (TABLOCK) (patientID_reg, tipoStatoClinico, dataStatoClinico, terapiaInCorso, terapia, intubato)
SELECT ISNULL(paz.value('(codiceRegionalePaziente/text())[1]', 'nvarchar(50)'),NULL) AS [patientID_reg]
,ISNULL(sc.value('(tipoStatoClinico/text())[1]', 'nvarchar(50)'),NULL) AS [tipoStatoClinico]
,ISNULL(sc.value('(dataStatoClinico/text())[1]', 'date'),NULL) AS [dataStatoClinico]
,ISNULL(sc.value('(terapiaInCorso/text())[1]', 'int'),0) AS [terapiaInCorso]
,ISNULL(sc.value('(terapiaDescrizione/text())[1]', 'nvarchar(1000)'),NULL) AS [terapia]
,ISNULL(sc.value('(intubato/text())[1]', 'int'),NULL) AS [intubato]
FROM
@XML.nodes('covid-19/pazienti/paziente') AS A(paz)
OUTER APPLY
paz.nodes('statiClinici/statoClinico') C(sc)
--OPTION (OPTIMIZE FOR UNKNOWN)
--OPTION (RECOMPILE)
-- stati clinici --
DECLARE @EndTimeInsertStatiClinici datetime = getdate()
SELECT DATEDIFF (SS ,@StarTimeInsertStatiClinici,@EndTimeInsertStatiClinici) AS StatiCliniciInsertDuration
--
--select * from XMLbulkLoad
DECLARE @EndTimeInsert datetime = getdate()
SELECT DATEDIFF (SS ,@StartTimeInsertPazienti,@EndTimeInsertStatiClinici) AS TotalInsertDuration
-- DROP temp tables
if object_id('tempdb..#xmlPazienti') is not null DROP TABLE #xmlPazienti;
if object_id('tempdb..#xmlCollocazioni') is not null DROP TABLE #xmlCollocazioni;
if object_id('tempdb..#xmlStatiClinici') is not null DROP TABLE #xmlStatiClinici;
The problem is that when there are a few hundred (or fewer) elements in the XML, the query performs just fine. However, when there are 25,000 elements, it takes 50 seconds to finish returning the rows in SSMS and I could have 50-100,000 elements.
Is there a more efficient way to transform the XML document into the tabular dataset (in SQL)?
回答1:
One general hint might be: create your indexes as the final step. Especially with a lot of rows this will slow down any data manipulation (in this case your insert statements);
As pointed in my comment you might walk the staging route.
First I create a mockup table to simulate your issue
DECLARE @tbl TABLE(YourXML XML);
INSERT INTO @tbl VALUES
(N'<covid-19 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://covid-19.iss.it/XMLSchema/0.1/">
<pazienti>
<paziente>
<codiceRegionalePaziente>0123456789</codiceRegionalePaziente>
<codiceFiscale/>
<nome>nomeBulk01</nome>
<cognome>cognomeBulk01</cognome>
<!-- shortened -->
<collocazioni>
<collocazione>
<dataCollocazione>2020-03-01</dataCollocazione>
<!-- shortened -->
</collocazione>
</collocazioni>
<statiClinici>
<statoClinico>
<tipoStatoClinico>Asintomatico</tipoStatoClinico>
<!-- shortened -->
</statoClinico>
<statoClinico>
<tipoStatoClinico>Lieve</tipoStatoClinico>
<!-- shortened -->
</statoClinico>
<statoClinico>
<tipoStatoClinico>Critico</tipoStatoClinico>
<!-- shortened -->
</statoClinico>
</statiClinici>
</paziente>
<paziente>
<codiceRegionalePaziente>AABB1234567890</codiceRegionalePaziente>
<codiceFiscale>AAABBB00C11D222E</codiceFiscale>
<nome>nomeBulk02</nome>
<cognome>cognomeBulk02</cognome>
<!-- shortened -->
<collocazioni>
<collocazione>
<dataCollocazione>2020-03-01</dataCollocazione>
<!-- shortened -->
</collocazione>
<collocazione>
<dataCollocazione>2020-03-05</dataCollocazione>
<!-- shortened -->
</collocazione>
</collocazioni>
<statiClinici>
<statoClinico>
<tipoStatoClinico>Pauci-sintomatico</tipoStatoClinico>
<!-- shortened -->
</statoClinico>
<statoClinico>
<tipoStatoClinico>Severo</tipoStatoClinico>
<!-- shortened -->
</statoClinico>
</statiClinici>
</paziente>
<paziente>
<codiceRegionalePaziente>9999999</codiceRegionalePaziente>
<codiceFiscale/>
<nome>nomeBulk03</nome>
<cognome>cognomeBulk03</cognome>
<!-- shortened -->
<collocazioni>
</collocazioni>
<statiClinici>
</statiClinici>
</paziente>
</pazienti>
</covid-19>');
--The query
WITH XMLNAMESPACES(DEFAULT 'http://covid-19.iss.it/XMLSchema/0.1/')
SELECT paz.value('(codiceRegionalePaziente/text())[1]', 'nvarchar(50)') AS [patientID_reg]
,paz.value('(codiceFiscale/text())[1]', 'varchar(16)') AS [codiceFiscale]
,paz.value('(cognome/text())[1]', 'nvarchar(255)') AS [cognome]
,paz.value('(nome/text())[1]', 'nvarchar(255)') AS [nome]
--shortended
,coll.value('(dataCollocazione/text())[1]', 'date') AS [dataRicovero]
--shortended
,sc.value('(tipoStatoClinico/text())[1]', 'nvarchar(50)') AS [tipoStatoClinico]
--shortended
--Define a target staging table simply automatically
INTO #StagingTable
FROM @tbl t
CROSS APPLY t.YourXML.nodes('covid-19/pazienti/paziente') AS A(paz)
OUTER APPLY
paz.nodes('collocazioni/collocazione') B(coll)
OUTER APPLY
paz.nodes('statiClinici/statoClinico') C(sc);
--now all your data is shifted into one big table
SELECT * FROM #StagingTable
--use something like this to get the patient data
SELECT patientID_reg,codiceFiscale,cognome,nome /*all patient related columns*/
FROM #StagingTable
GROUP BY patientID_reg,codiceFiscale,cognome,nome /*all patient related columns*/;
--This will your related data.
SELECT patientID_reg,dataRicovero /*all collocazioni related data*/
FROM #StagingTable
GROUP BY patientID_reg,dataRicovero /*all collocazioni related data*/
SELECT patientID_reg,tipoStatoClinico /*all stati clinici related data*/
FROM #StagingTable
GROUP BY patientID_reg,tipoStatoClinico /*all stati clinici related data*/
You can perform any cleaning, or check of business logic, against the staged data. It might be a good idea to check for existing patientID_reg
values in your target table...
Then shift the cleaned data into your final target tables.
UPDATE
Attention: If your XML might carry the same patientID_reg
value for different elements you will have to add a ROW_NUMBER()
In this case you might use something along this:
WITH XMLNAMESPACES(DEFAULT 'http://covid-19.iss.it/XMLSchema/0.1/')
,ReadPatientDataWithRowNumber AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS PatientNumber
,paz.value('(codiceRegionalePaziente/text())[1]', 'nvarchar(50)') AS [patientID_reg]
,paz.value('(codiceFiscale/text())[1]', 'varchar(16)') AS [codiceFiscale]
,paz.value('(cognome/text())[1]', 'nvarchar(255)') AS [cognome]
,paz.value('(nome/text())[1]', 'nvarchar(255)') AS [nome]
--shortended
,paz.query('collocazioni/collocazione') AS CollocazioneXml
,paz.query('statiClinici/statoClinico') AS StatoClinicoXml
FROM @tbl t
CROSS APPLY t.YourXML.nodes('covid-19/pazienti/paziente') AS A(paz)
)
,AddTheRest AS
(
SELECT pd.*
,coll.value('(dataCollocazione/text())[1]', 'date') AS [dataRicovero]
--shortended
,sc.value('(tipoStatoClinico/text())[1]', 'nvarchar(50)') AS [tipoStatoClinico]
--shortended
FROM ReadPatientDataWithRowNumber pd
OUTER APPLY
pd.CollocazioneXml.nodes('collocazioni/collocazione') B(coll)
OUTER APPLY
pd.StatoClinicoXml.nodes('statiClinici/statoClinico') C(sc)
)
SELECT *
INTO #StagingTable
FROM AddTheRest
SELECT PatientNumber,patientID_reg,codiceFiscale,cognome,nome /*all patient related columns*/
FROM #StagingTable
GROUP BY PatientNumber,patientID_reg,codiceFiscale,cognome,nome /*all patient related columns*/;
SELECT PatientNumber,patientID_reg,dataRicovero /*all collocazioni related data*/
FROM #StagingTable
GROUP BY PatientNumber,patientID_reg,dataRicovero /*all collocazioni related data*/
SELECT PatientNumber,patientID_reg,tipoStatoClinico /*all stati clinici related data*/
FROM #StagingTable
GROUP BY PatientNumber,patientID_reg,tipoStatoClinico /*all stati clinici related data*/
UPDATE 2
Please check this:
WITH XMLNAMESPACES(DEFAULT 'http://covid-19.iss.it/XMLSchema/0.1/')
,ReadPatientDataWithRowNumber AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS PatientNumber
,paz.value('(codiceRegionalePaziente/text())[1]', 'nvarchar(50)') AS [patientID_reg]
,paz.value('(codiceFiscale/text())[1]', 'varchar(16)') AS [codiceFiscale]
,paz.value('(cognome/text())[1]', 'nvarchar(255)') AS [cognome]
,paz.value('(nome/text())[1]', 'nvarchar(255)') AS [nome]
--shortended
,paz.query('collocazioni/collocazione') AS CollocazioneXml
,paz.query('statiClinici/statoClinico') AS StatoClinicoXml
FROM @tbl t
CROSS APPLY t.YourXML.nodes('covid-19/pazienti/paziente') AS A(paz)
)
SELECT *
INTO #StagingTable
FROM ReadPatientDataWithRowNumber
SELECT * FROM #StagingTable;
来源:https://stackoverflow.com/questions/61608313/efficient-way-to-transform-xml-document-into-tabular-dataset-in-sql-because-cros