Il tipo di dati XML in SQL Server 2005 è presente in due forme: non tipizzato (forma debole) e tipizzato (forma forte). Nel primo caso per poter archiviare il codice XML è necessario che esso sia ben formato, nel secondo invece, deve anche aderire alle regole definite nello schema XSD a cui fa riferimento. Quest'ultima soluzione è sicuramente la forma migliore di archiviazione dei dati XML perché permette di memorizzare istanze sempre valide e univocamente interpretabili in base allo schema XSD.
In questo articolo illustreremo i passi necessari per creare ed usare istanze di dati XML in forma tipizzata.
Cos'è uno schema XSD?
Uno schema XSD è un'insieme di regole (codificate in un documento dal formato XML) che definiscono la struttura di un documento XML realizzato secondo le linee guida del W3C. Esso rende univocamente leggibili i dati scambiati tramite un documento XML fornendo diversi strumenti di controllo, tra i quali ricordiamo:
- Definizione di tipi complessi e controllo sulla posizione e sul numero di volte che possono apparire nel documento.
- Annotazioni e commenti per rendere leggibile il documento.
- Introduzioni di elementi Nulli.
- Definizione di elementi Unici.
- Definizione di Chiavi e Relazioni.
Listato 1. Esempio di schema XSD
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="libro">
<xs:complexType>
<xs:sequence>
<xs:element name="autore" type="xs:string" />
<xs:element name="titolo" type="xs:string" />
<xs:element name="numeroPagine" type="xs:integer" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Lo schema rappresentato è una collezione di dichiarazioni di elemento e di attributo, in cui all'interno di ognuna è necessario specificare un tipo dati. I tipi primitivi, come string, float, int, ecc..sono presi da http://www.w3.org/2001/XMLSchema
. Per approfondire l'argomento vi consiglio di leggere la guida all'XML pubblicata sul sito http://xml.html.it/guide/leggi/58/guida-xml-di-base.
Il tipo XML tipizzato dietro le quinte.
Se vengono abbinati uno o più schema XSD ad un documento XML, allora il documento XML si dice tipizzato. Lo schema in questione ha il compito di fornire:
- Vincoli di convalida.
- Informazioni sul tipo di dati dell'istanza (gli elementi e gli attributi validi, i namespace, etc.)
Ogni volta che un documento XML tipizzato viene memorizzato su un database SQL Server svolge internamente alcune operazioni:
- Valida automaticamente i dati in base allo schema associato alla colonna, al parametro o alla variabile xml.
- Memorizza il contenuto di elementi e attributi in forma tipizzata all'interno di una rappresentazione binaria (XML Blob) molto più efficiente di quella testuale (costituita da insieme di caratteri Unicode) usata per l'xml non tipizzato.
Sostanzialmente avviene una sorta di mappatura/conversione tra i tipi dati di SQL Server e gli appropriati e corrispondenti tipi dati definiti nello schema XSD.
Migliorare le prestazioni delle query
Usare istanze dati XML tipizzate ha un impatto positivo dal punto di vista prestazionale nelle interrogazioni fatte tramite il linguaggio XQuery. SQL Server ricava dallo schema XSD informazioni preziose sulla tipologia dei dati contenuti nell'istanza xml inserita, riuscendo così a:
- Ottimizzare l'utilizzo di indici sulle colonne con istanze dati XML tipizzate.
- Evitare la conversione a runtime dei data type dei nodi valore dell'istanza XML.
A giovare maggiormente delle informazioni aggiuntive apportate dallo schema è il compilatore XQuery, infatti conoscere a priori i data type implicati nelle query mette in grado il compilatore di redigere piani di esecuzione più accurati e precisi evitando ad esempio inutili conversioni tra i diversi tipi dati, errori e controlli sulla correttezza semantica delle query.
Supponiamo di avere una query simile (/libro/prezzo)[1] > 30.9
, nel caso di XML non tipizzato il valore del nodo prezzo viene considerato come una stringa e solo successivamente, al momento della comparazione, viene convertito nel formato decimale.
Al contrario, se l'istanza dati XML fosse stata tipizzata, il compilatore avrebbe potuto risparmiare il costo della conversione numerica da stringa a decimale in quanto avrebbe saputo, fin dalla memorizzazione dei dati, che il nodo prezzo conteneva un tipo dati decimale.
Creare colonne XML tipizzate
Per creare colonne o parametri o variabili XML tipizzate generalmente valgono le stesse considerazioni (sintassi, istruzioni, costrutti, ecc...) viste nel precedente articolo. Supponiamo di voler creare una tabella SQL con una colonna XML tipizzata in grado di memorizzare istanze XML contenenti i dati salienti di un libro, le informazioni potrebbero essere queste:
Listato 2. Dettaglio di un libro in formato xml
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="libro">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="autore" type="xsd:string" />
<xsd:element name="titolo" type="xsd:string" />
<xsd:element name="numeroPagine" type="xsd:integer" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Il primo passo da compiere per creare una colonna XML tipizzata è produrre lo schema XSD che descriva correttamente l'istanza dati xml da memorizzare.
Listato 2. Schema XSD che descrive i dettagli di un libro
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="libro">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="autore" type="xsd:string" />
<xsd:element name="titolo" type="xsd:string" />
<xsd:element name="numeroPagine" type="xsd:integer" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Lo schema è formato da una sequenza di tre elementi: <autore>
, <titolo>
e <numeroPagine>
contenuti da un elemento radice denominato <libro>
. I tipi dati utilizzati sono semplici: stringhe e interi.
Il secondo passo consiste nell'aggiungere lo schema appena creato alla collezione di schema XSD del database. Per farlo usiamo una nuova istruzione: CREATE XML SCHEMA COLLECTION
(la gestione completa degli schema verrà approfondita in seguito).
Listato 4. Creazione e aggiunta dello schema DettagliLibroSchemaColl
CREATE XML SCHEMA COLLECTION DettagliLibroSchemaColl AS
'<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">... CONTENUTO DELLO SCHEMA XSD'
Ora che abbiamo creato e aggiunto alla collezione lo schema denominato DettagliLibroSchemaColl possiamo compiere il terzo e ultimo passo: associare lo schema ad una colonna XML.
Listato 5. Creazione della colonna XmlDetails con abbinato lo schema DettagliLibroSchemaColl
CREATE TABLE [dbo].[Product]
(
[ProductId] [int] NOT NULL,
[ProductName] [nvarchar](128),
[XmlDetails] [xml] (DettagliLibroSchemaColl) NOT NULL
)
La sintassi è identica a quella già vista per creare colonne XML non tipizzate, l'unica differenza consiste nell'aggiungere a fianco del tipo dati XML il nome dello schema XSD abbinato. La stessa cosa può ovviamente essere fatta per le variabili o i parametri di tipo XML.
Listato 6. Creazione di una variabile e un parametro con abbinato lo schema DettagliLibroSchemaColl
declare @xmldet xml (DettagliLibroSchemaColl)
--oppure
create procedure prc_XML as @XmlDetails [xml] (DettagliLibroSchemaColl)
Ora la colonna XmlDetails
potrà contenere solo istanze XML valide e conformi allo schema XSD DettagliLibroSchemaColl
, in caso contrario SQL Server produrrà un errore e rigetterà l'inserimento dei dati.
Listato 7. Esempi di inserimenti di dati XML nella colonna XmlDetails
--Inserimento valido
insert into Product values (1,'libro 1','<libro><autore>luca milan</autore><titolo>Le novità XML in SQL Server 2005</titolo><numeroPagine>50</numeroPagine></libro>')
--Inserimento non corretto, ho invertito l'ordine degli elementi titolo e autore
insert into Product values (1,'libro 1','<libro><titolo>Le novità XML in SQL Server 2005</titolo><autore>luca milan</autore><numeroPagine>50</numeroPagine></libro>')
Convertire istanze dati XML da non tipizzate a tipizzate.
Quest'operazione (e viceversa) è possibile a patto che esista lo schema XSD che vogliamo associare alla colonna, parametro o variabile XML e che i dati da convertire siamo coerenti con il tipo di operazione (a seconda dei casi dovranno essere ben formati e validi).
Listato 8. Esempi conversione da/a xml tipizzato e non
CREATE TABLE [dbo].[Product](
[ProductId] [int] NOT NULL,
[ProductName] [nvarchar](128),
[XmlDetails] [xml] NOT NULL
)
--Modifico la definizione della colonna XmlDetails abbinado lo schema DettagliLibroSchemaColl
ALTER TABLE [Product]
ALTER COLUMN [XmlDetails] [xml] (DettagliLibroSchemaColl) NOT NULL
Avremmo anche potuto definire la colonna XmlDetails
con un tipo dati varchar(max)
e la conversione avrebbe avuto luogo correttamente.