Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Der beste Weg, um XML-Daten in SQL Server-Datenbankspalten zu schreddern

Ich bin über diese Frage gestolpert, während ich ein sehr ähnliches Problem hatte. Ich hatte eine Abfrage ausgeführt, bei der eine 7,5-MB-XML-Datei (ca. 10.000 Knoten) etwa 3,5 bis 4 Stunden lang verarbeitet wurde, bevor ich schließlich aufgab.

Nach ein wenig mehr Recherche fand ich jedoch heraus, dass nach dem Eingeben des XML-Codes mithilfe eines Schemas und dem Erstellen eines XML-Index (ich würde ihn massenweise in eine Tabelle einfügen) die gleiche Abfrage in ~ 0,04 ms abgeschlossen war.

Wie ist das für eine Leistungssteigerung!

Code zum Erstellen eines Schemas:

IF EXISTS ( SELECT * FROM sys.xml_schema_collections where [name] = 'MyXmlSchema')
DROP XML SCHEMA COLLECTION [MyXmlSchema]
GO

DECLARE @MySchema XML
SET @MySchema = 
(
    SELECT * FROM OPENROWSET
    (
        BULK 'C:\Path\To\Schema\MySchema.xsd', SINGLE_CLOB 
    ) AS xmlData
)

CREATE XML SCHEMA COLLECTION [MyXmlSchema] AS @MySchema 
GO

Code zum Erstellen der Tabelle mit einer typisierten XML-Spalte:

CREATE TABLE [dbo].[XmlFiles] (
    [Id] [uniqueidentifier] NOT NULL,

    -- Data from CV element 
    [Data] xml(CONTENT dbo.[MyXmlSchema]) NOT NULL,

CONSTRAINT [PK_XmlFiles] PRIMARY KEY NONCLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

Code zum Erstellen des Index

CREATE PRIMARY XML INDEX PXML_Data
ON [dbo].[XmlFiles] (Data)

Es gibt jedoch ein paar Dinge zu beachten. Die SQL Server-Implementierung von Schema unterstützt xsd:include nicht. Das bedeutet, dass Sie, wenn Sie ein Schema haben, das auf ein anderes Schema verweist, alle diese in ein einziges Schema kopieren und dieses hinzufügen müssen.

Außerdem würde ich eine Fehlermeldung erhalten:

XQuery [dbo.XmlFiles.Data.value()]: Cannot implicitly atomize or apply 'fn:data()' to complex content elements, found type 'xs:anyType' within inferred type 'element({http://www.mynamespace.fake/schemas}:SequenceNumber,xs:anyType) ?'.

wenn ich versuchte, über den Knoten zu navigieren, den ich mit der Knotenfunktion ausgewählt hatte. Z. B.

SELECT
    ,C.value('CVElementId[1]', 'INT') AS [CVElementId]
    ,C.value('../SequenceNumber[1]', 'INT') AS [Level]
FROM 
    [dbo].[XmlFiles]
CROSS APPLY
    [Data].nodes('/CVSet/Level/CVElement') AS T(C)

Es wurde festgestellt, dass der beste Weg, dies zu handhaben, darin bestand, das OUTER APPLY zu verwenden, um tatsächlich eine "äußere Verknüpfung" für das XML durchzuführen.

SELECT
    ,C.value('CVElementId[1]', 'INT') AS [CVElementId]
    ,B.value('SequenceNumber[1]', 'INT') AS [Level]
FROM 
    [dbo].[XmlFiles]
CROSS APPLY
    [Data].nodes('/CVSet/Level') AS T(B)
OUTER APPLY
    B.nodes ('CVElement') AS S(C)

Hoffe, dass das jemandem hilft, denn das war so ziemlich mein Tag.