Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Stocker des données XML dans SQL Server

Lors du travail sur la publication de dbForge Transaction Log, entre autres tâches, notre équipe a dû se demander comment stocker correctement les données XML typées.

Pour commencer, il convient de mentionner que SQL Server ne stocke pas XML dans le format dans lequel il a été saisi. Une chaîne XML est analysée, divisée en balises et est donc stockée dans un format compressé. Les éléments de description que le serveur considère comme inutiles sont ignorés.

Il convient également de garder à l'esprit que, si le type de données d'une colonne est spécifié en XML simple, le serveur stockera ces données sous forme de chaînes Unicode.
Exemple 1.

CREATE TABLE XmlValuesTable ( [uid] [int] IDENTITY PRIMARY KEY, v XML NOT NULL );GOINSERT INTO XmlValuesTable (v)VALUES ('123.456');INSERT INTO XmlValuesTable (v)VALUES ('4.0000000000');

Le serveur stockera l'insert données comme suit :

 F0 04 6E006F0074006500 <- Nom "Remarque" EF 000001 <- Espace de noms 01f8 01 <- TAG 01F0 05 66006C006F0061007400 <- Nom "Float" EF 000002 <- Namespace 02F8 02 <- TAGE 0211 07 31003200300330020026 F7 <- balise de fermetureF0 04 740069006D006500 <- Nom "heure"EF 000003 <- Espace de noms 02F8 03 <- balise 0311 0C 300031003A00320033003A00340035002E00370038-8 balise de fermetureFpre
 Dans l'exemple suivant, le type de données de la colonne est spécifié tel qu'il a été tapé via XML Schema Collection.

Exemple 2.

CRÉER UNE COLLECTION DE SCHÉMA XML [XmlValuesSchemaCollection_datetime2] AS'  ';GOCREATE TABLE XmlValuesTable_datetime2 ( [uid] [ int] CLÉ PRIMAIRE D'IDENTITÉ, v XML(XmlValuesSchemaCollection_datetime2) NOT NULL);GOINSERT INTO XmlValuesTable_datetime2 (v)VALUES (N'2014-06-18T06:39:05.190');GO

Dans ce cas particulier, le serveur stockera l'insert données comme suit :

 EA 09 014C010015 1A000000 <- Type Info 0x14c (332) «DateTime2», 0x15 (21) «DateTime» + Offsetf0 09 6400610074006500740069006D0065003200 <- Name »Datetime2" Ef 000001 <- NamesPace 01f8 01f 01 0044c 01 0044C011 - tapez info7E 02978924A9380B <- "2014-06-18T06:39:05.190"F7 <- balise de fermeture

De cette manière, le serveur convertit les données stockées en types spécifiés dans l'addendum à cet article (vous pouvez voir la liste de tous les types de données en exécutant la requête "select * from sys.xml_schema_types" sur le serveur).

Voyons comment le serveur enregistrera une structure plus complexe similaire à celle de l'exemple 1 et décrite avec XML Schema Collection.

Exemple 3.

CRÉER UNE COLLECTION DE SCHÉMA XML [XmlValuesSchemaCollection] AS'          ' ; GO CREATE TABLE XmlValuesTable ( [uid] [int] IDENTITY PRIMARY KEY, v XML(XmlValuesSchemaCollection) NOT NULL);GOINSERT INTO XmlValuesTable (v)VALUES ('123.456');

Le serveur enregistrera l'insert données comme suit :

EA 05 0001000100 <- type infoF0 04 6E006F0074006500 <- Name "note"EF 000001 <- NamespaceF8 01 <- tag 01EA 09 0111000011 12000000 <- type info 0x11 (17) "float" + offsetF0 04 66006 float"EF 000002 <- NamespaceF8 02 <- tag 02EA 05 0011000011 <- type info 0x11 (17) "float"03 79E9F642 <- "123.456"F7 <- fermeture tagEA 09 0116000016 10000000 <- type info 0x16 (22) "time " + offsetF0 04 740069006D006500 <- Name "time"EF 000003 <- NamespaceF8 03 <- tag 03EA 05 0016000016 <- type info 0x16 (22) "time"7D 03FDAF4C005B950A <- "01:23:45.789"F7 <- tag de fermetureF7 <- balise de fermeture

Essayons d'ajouter un lien de schéma à l'insert.

Exemple 4.

INSERT INTO XmlValuesTable (v)VALUES ('123.456');
 EA 05 0001000100 <- Type Infof0 04 6E006F0074006500 <- Nom "Remarque" EF 000001 <- namespacef8 01 <- TAG 01F0 09 78006D006C006E0073003A00780073006900 <- Nom " <- Attribute11 29 68007400740070003A002F002F007700770077002E00770033002E006F00720067002F0032003000300031002F0058004D004C0053006300680065006D0061002D0069006E007300740061006E0063006500 <- "http://www.w3.org/2001/XMLSchema-instance"F5 <- closing bracketEA 09 0111000011 12000000 <- type info 0x11 (17) "float" + offsetF0 05 66006C006F0061007400 <- Name "float"EF 000003 <- NamespaceF8 03 <- tag 03EA 05 0011000011 <- type info 0x11 (17) "float"03 79E9F642 <- "123.456"F7 <- fermeture tagEA 09 0116000016 10000000 <- type info 0x16 (22) " time" + offsetF0 04 740069006D006500 <- Name "time"EF 000004 <- NamespaceF8 04 <- tag 08EA 05 0016000016 <- type info 0x16 (22) "time"7D 03FDAF4C005B950A <- "01:23:45.789"F7 <- fermeture tagF7 <- balise de fermeture

Comme vous pouvez le voir, le serveur a soigneusement enregistré l'espace de noms en tant qu'attribut et a utilisé près de la moitié de l'espace pour cela, même en dépit du fait que l'espace de noms ne sert à rien ici - les données ont été enregistrées de la même manière qu'elles le seraient enregistré sans l'espace de noms.

Conclusion

D'après ce qui précède, il peut sembler que vous pouvez réduire la taille d'une base de données en stockant certains types de données (par exemple, float) sous forme de valeurs typées, car 4 octets nécessitent beaucoup moins de stockage que la même valeur enregistrée sous forme de chaîne Unicode. Cependant, vous devez garder à l'esprit que 7 à 18 octets supplémentaires sont utilisés pour chaque valeur afin de décrire son type et de la déplacer à la position nécessaire.

Avenant

Corrélation des types XML, des types de base et des types de données que le serveur utilise pour stocker les valeurs typées.

Type XML Type de base Stocké en tant que type Taille en octets
tout type chaîne 2 * caractères
toutSimpleType n'importe quel type chaîne
chaîne toutSimpleType chaîne
booléen toutSimpleType booléen 1
flottant toutSimpleType flottant 4
doubler toutSimpleType doubler 8
décimal toutSimpleType SqlDecimal 20
durée toutSimpleType chaîne
dateHeure toutSimpleType *1
heure toutSimpleType *1
date toutSimpleType *1
gAnnéeMois toutSimpleType chaîne
gAnnée toutSimpleType chaîne
gMoisJour toutSimpleType chaîne
gJour toutSimpleType chaîne
gMois toutSimpleType chaîne
hexBinary toutSimpleType tableau d'octets
base64Binary toutSimpleType tableau d'octets
toutURI toutSimpleType chaîne
QName toutSimpleType chaîne
chaîne normalisée chaîne chaîne
jeton chaîne chaîne
langue chaîne chaîne
Nom chaîne chaîne
NCName chaîne chaîne
ENTITÉ chaîne chaîne
NMTOKEN chaîne chaîne
entier décimal SqlDecimal 20
NonPositiveInteger entier SqlDecimal 20
Entier négatif NonPositiveInteger SqlDecimal 20
longue entier SqlDecimal 20
entier longue SqlDecimal 20
court entier SqlDecimal 20
octet court SqlDecimal 20
nonNegativeInteger entier SqlDecimal 20
unsignedLong nonNegativeInteger SqlDecimal 20
unsignedInt unsignedLong SqlDecimal 20
court non signé unsignedInt SqlDecimal 20
unsignedByte court non signé SqlDecimal 20
Entierpositif nonNegativeInteger SqlDecimal 20
caractère chaîne chaîne
nchar chaîne chaîne
varchar chaîne chaîne
nvarchar chaîne chaîne
texte chaîne chaîne
texte chaîne chaîne
varbinaire base64Binary tableau d'octets
binaire base64Binary tableau d'octets
image base64Binary tableau d'octets
horodatage base64Binary tableau d'octets
timestampNumeric longue SqlDecimal 20
numérique décimal SqlDecimal 20
bigint longue SqlDecimal 20
smallint court SqlDecimal 20
tinyint unsignedByte SqlDecimal 20
bit booléen booléen 1
réel flottant flottant 4
dateheure dateHeure *1
smalldatetime dateHeure *1
l'argent décimal SqlDecimal
petite monnaie décimal SqlDecimal
identifiant unique décimal chaîne
dateheure2 dateHeure *1
datetimeoffset dateHeure *1
hierarchyid chaîne chaîne
dbobject toutURI chaîne

*1 – informations sur les données/l'heure. Le type spécifique est défini par la valeur.

Valeur Stocké en tant que type Taille en octets
DateOffset Date (nombre de jours) 3
DateOffset (2019-09-16+02:00) DateTimeOffset 11
DateHeure DateHeure 7-9 dépend de la précision
DateTimeOffset DateTimeOffset 9
Heure DateHeure 7-9 dépend de la précision
TimeOffset (01:23:45Z) DateTimeOffset 9