Tipi di dati XPath (SQLXML 4.0)
Si applica a: SQL Server
Database SQL di Azure
Microsoft SQL Server, XPath e XML Schema (XSD) hanno tipi di dati molto diversi. Ad esempio, XPath non ha tipi di dati integer o date, ma SQL Server e XSD hanno molti. XSD usa la precisione nanoseconda per i valori temporali e SQL Server usa al massimo la precisione di 1/300 secondi. Di conseguenza, il mapping di un tipo di dati a un altro non è sempre possibile. Per altre informazioni sul mapping dei tipi di dati di SQL Server ai tipi di dati XSD, vedere Coercizione dei tipi di dati e annotazione sql:datatype (SQLXML 4.0).
XPath ha tre tipi di dati: stringa, numero e booleano. Il tipo di dati number è sempre un tipo di dati IEEE 754 a precisione doppia a virgola mobile. Il tipo di dati float(53) di SQL Serverè il numero XPath più vicino. Tuttavia, float(53) non è esattamente IEEE 754. Ad esempio, non viene utilizzato né un valore diverso da un numero (NaN, Not-a-Number) né un valore infinito. Il tentativo di convertire una stringa non numerica in numero e tentare di dividere per zero genera un errore.
Conversioni XPath
Quando si utilizza una query XPath, ad esempio OrderDetail[@UnitPrice > "10.0"]
, le conversioni dei tipi di dati implicite ed esplicite possono modificare impercettibilmente il significato della query. È pertanto importante comprendere le modalità di implementazione dei tipi di dati XPath. La specifica del linguaggio XPath, XPath Path Language (XPath) versione 1.0 W3C Proposta raccomandazione 8 ottobre 1999, è disponibile nel sito Web W3C all'indirizzo http://www.w3.org/TR/1999/PR-xpath-19991008.html.
Gli operatori XPath sono suddivisi in quattro categorie:
Operatori booleani (and, or)
Operatori relazionali (<, >, <=, >=)
Operatori di uguaglianza (=, !=)
Operatori aritmetici: (+, -, *, div, mod)
Ogni categoria di operatore converte in modo diverso gli operandi. Se necessario, gli operatori XPath convertono gli operandi in modo implicito. Gli operatori aritmetici convertono gli operandi in numero e generano un valore numerico. Gli operatori booleani convertono gli operandi in valori booleani e generano un valore booleano. Gli operatori relazionali e gli operatori di uguaglianza restituiscono un valore booleano, ma utilizzano regole di conversione diverse a seconda dei tipi di dati originali degli operandi, come illustrato nella tabella seguente.
Operand | Operatore relazionale | Operatore di uguaglianza |
---|---|---|
Entrambi gli operandi sono set di nodi. | TRUE se e solo se è presente un nodo in un set e un nodo nel secondo set in modo che il confronto dei valori stringa sia TRUE. | Stessa operazione. |
Uno è un set di nodi, l'altro una stringa. | TRUE se e solo se è presente un nodo nel set di nodi in modo che, quando viene convertito in numero, il confronto con la stringa convertita in numero è TRUE. | TRUE se e solo se è presente un nodo nel set di nodi in modo che, quando viene convertito in stringa, il confronto con la stringa è TRUE. |
Uno è un set di nodi, l'altro un numero. | TRUE se e solo se è presente un nodo nel set di nodi in modo che quando viene convertito in numero, il confronto con il numero è TRUE. | Stessa operazione. |
Uno è un set di nodi, l'altro un valore booleano. | TRUE se e solo se è presente un nodo nel set di nodi in modo che, se convertito in booleano e quindi in numero, il confronto con il valore booleano convertito in numero è TRUE. | TRUE se e solo se è presente un nodo nel set di nodi in modo che, quando convertito in booleano, il confronto con il valore booleano è TRUE. |
Nessuno è un set di nodi. | Convertire entrambi gli operandi in numero e quindi confrontarli. | Convertire entrambi gli operandi in un tipo comune e quindi eseguire il confronto. Convertire in valore booleano se uno dei due è booleano, numero se uno dei due è numerico; in caso contrario, convertire in stringa. |
Nota
Poiché gli operatori relazionali XPath convertono sempre gli operandi in numero, i confronti tra stringhe non sono possibili. Per includere confronti di date, SQL Server 2000 offre questa variante alla specifica XPath: quando un operatore relazionale confronta una stringa con una stringa, un set di nodi a una stringa o un set di nodi con valori stringa su un set di nodi con valori stringa, viene eseguito un confronto di stringhe (non un confronto numerico).
Conversioni dei set di nodi
Le conversioni dei set di nodi non sono sempre intuitive. Un set di nodi viene convertito in una stringa accettando il valore stringa solo del primo nodo nel set. Un set di nodi viene convertito in numero convertendolo in stringa e quindi convertendo la stringa in numero. Un set di nodi viene convertito in booleano testandone l'esistenza.
Nota
SQL Server non esegue la selezione posizionale nei set di nodi: ad esempio, la query Customer[3]
XPath indica il terzo cliente. Questo tipo di selezione posizionale non è supportato in SQL Server. Pertanto, le conversioni node-set-to-string o node-set-to-number come descritto dalla specifica XPath non vengono implementate. SQL Server usa la semantica "any" ovunque la specifica XPath specifichi la semantica "first". Ad esempio, in base alla specifica XPath W3C, la query Order[OrderDetail/@UnitPrice > 10.0]
XPath seleziona gli ordini con il primo OrderDetail con unitPrice maggiore di 10,0. In SQL Server questa query XPath seleziona gli ordini con qualsiasi OrderDetail con unitPrice maggiore di 10.0.
La conversione in un valore booleano genera un test di esistenza, pertanto la query Products[@Discontinued=true()]
XPath equivale all'espressione SQL "Products.Discontinued non è null", non all'espressione SQL "Products.Discontinued = 1". Per rendere la query equivalente alla seconda espressione SQL, convertire prima il set di nodi in un tipo non booleano , ad esempio number. Ad esempio: Products[number(@Discontinued) = true()]
.
Poiché la maggior parte degli operatori viene definita come TRUE se gli operatori sono TRUE per tutti i nodi nel set di nodi o per uno di essi, queste operazioni restituiscono sempre FALSE se il set di nodi è vuoto. In questo modo, se A è vuoto, sia A = B
sia A != B
sono FALSE e not(A=B)
e not(A!=B)
sono TRUE.
In genere, esiste un attributo o un elemento mappato a una colonna se il valore di tale colonna nel database non è Null. Sono presenti elementi di cui è stato eseguito il mapping a righe se è presente uno qualunque dei figli.
Nota
Gli elementi annotati con is-constant esistono sempre. Di conseguenza, i predicati XPath non possono essere utilizzati su elementi costanti .
Quando un set di nodi viene convertito in stringa o numero, il tipo XDR (se presente) viene controllato nello schema con annotazioni e tale tipo viene usato per determinare la conversione necessaria.
Mapping di tipi di dati XDR a tipi di dati XPath
Il tipo di dati XPath di un nodo deriva dal tipo di dati XDR nello schema, come illustrato nella tabella seguente (il nodo EmployeeID viene usato a scopo illustrativo).
Tipo di dati XDR | Equivalente Tipo di dati XPath |
Conversione SQL Server utilizzata |
---|---|---|
Nonebin.base64bin.hex | N/D | NoneEmployeeID |
boolean | boolean | CONVERT(bit, EmployeeID) |
number, int, float, i1, i2, i4, i8,r4, r8ui1, ui2, ui4, ui8 | number | CONVERT(float(53), EmployeeID) |
id, idref, idrefsentity, entities, enumerationnotation, nmtoken, nmtokens, chardate, Timedate, Time.tz, string, uri, uuid | string | CONVERT(nvarchar(4000), EmployeeID, 126) |
fixed14.4 | N/D (in XPath non è disponibile alcun tipo di dati equivalente al tipo di dati XDR fixed14.4). | CONVERT(money, EmployeeID) |
data | string | LEFT(CONVERT(nvarchar(4000), EmployeeID, 126), 10) |
Ora time.tz |
string | SUBSTRING(CONVERT(nvarchar(4000), EmployeeID, 126), 1 + CHARINDEX(N'T', CONVERT(nvarchar(4000), EmployeeID, 126)), 24) |
Le conversioni di data e ora sono progettate per funzionare se il valore viene archiviato nel database usando il tipo di dati datetime di SQL Servero una stringa. Si noti che il tipo di dati datetime di SQL Servernon usa il fuso orario e ha una precisione inferiore al tipo di dati ora XML. Per includere il tipo di dati del fuso orario o una precisione aggiuntiva, archiviare i dati in SQL Server usando un tipo stringa .
Quando un nodo viene convertito dal relativo tipo di dati XDR al tipo di dati XPath, è talvolta necessaria un'ulteriore conversione (da un tipo di dati XPath a un altro tipo di dati XPath). Si consideri, ad esempio, la query XPath seguente:
(@m + 3) = 4
Se @m è del tipo di dati fixed14.4 XDR, la conversione dal tipo di dati XDR al tipo di dati XPath viene eseguita usando:
CONVERT(money, m)
In questa conversione il nodo m
viene convertito da fixed14.4 a money. Per aggiungere il valore 3, tuttavia, è necessaria un'ulteriore conversione:
CONVERT(float(CONVERT(money, m))
L'espressione XPath viene valutata nel modo seguente:
CONVERT(float(CONVERT(money, m)) + CONVERT(float(53), 3) = CONVERT(float(53), 3)
Come illustrato nella tabella seguente, si tratta della stessa conversione applicata per altre espressioni XPath, ad esempio i valori letterali o le espressioni composte.
X non è noto | X è stringa | X è il numero | X è booleano | |
---|---|---|---|---|
string(X) | CONVERT (nvarchar(4000), X, 126) | - | CONVERT (nvarchar(4000), X, 126) | CASE WHEN X THEN N'true' ELSE N'false' END |
number(X) | CONVERT (float(53), X) | CONVERT (float(53), X) | - | CASE WHEN X THEN 1 ELSE 0 END |
boolean(X) | - | LEN(X) > 0 | X != 0 | - |
Esempi
R. Convertire un tipo di dati in una query XPath
Nella query XPath seguente specificata su uno schema XSD con annotazioni, la query seleziona tutti i nodi Employee con il valore dell'attributo EmployeeID di E-1, dove "E-" è il prefisso specificato usando l'annotazione sql:id-prefix .
Employee[@EmployeeID="E-1"]
Il predicato nella query equivale all'espressione SQL:
N'E-' + CONVERT(nvarchar(4000), Employees.EmployeeID, 126) = N'E-1'
Poiché EmployeeID è uno dei valori del tipo di dati id (idref, idrefs, nmtoken, nmtokens e così via) nello schema XSD, EmployeeID viene convertito nel tipo di dati XPath stringa usando le regole di conversione descritte in precedenza.
CONVERT(nvarchar(4000), Employees.EmployeeID, 126)
Il prefisso "E-" viene aggiunto alla stringa, e il risultato viene quindi confrontato con N'E-1'
.
B. Eseguire diverse conversioni dei tipi di dati in una query XPath
Considerare la seguente query XPath specificata su uno schema XSD con annotazioni: OrderDetail[@UnitPrice * @OrderQty > 98]
Questa query XPath restituisce tutti gli elementi OrderDetail> che soddisfano il predicato @UnitPrice * @OrderQty > 98
.< Se UnitPrice è annotato con un tipo di dati fixed14.4 nello schema con annotazioni, questo predicato equivale all'espressione SQL:
CONVERT(float(53), CONVERT(money, OrderDetail.UnitPrice)) * CONVERT(float(53), OrderDetail.OrderQty) > CONVERT(float(53), 98)
Nel convertire i valori nella query XPath, la prima operazione converte il tipo di dati XDR nel tipo di dati XPath. Poiché il tipo di dati XSD di UnitPrice è fisso14.4, come descritto nella tabella precedente, si tratta della prima conversione usata:
CONVERT(money, OrderDetail.UnitPrice))
Poiché gli operatori aritmetici convertono gli operandi nel tipo di dati XPath numerico, viene applicata la seconda conversione (da un tipo di dati XPath a un altro tipo di dati XPath) in cui il valore viene convertito in float(53) (float(53) è vicino al tipo di dati numero XPath):
CONVERT(float(53), CONVERT(money, OrderDetail.UnitPrice))
Supponendo che l'attributo OrderQty non abbia un tipo di dati XSD, OrderQty viene convertito in un tipo di dati XPath numerico in una singola conversione:
CONVERT(float(53), OrderDetail.OrderQty)
Analogamente, il valore 98 viene convertito nel tipo di dati XPath numero :
CONVERT(float(53), 98)
Nota
Se il tipo di dati XSD usato nello schema non è compatibile con il tipo di dati SQL Server sottostante nel database o se viene eseguita una conversione impossibile del tipo di dati XPath, SQL Server potrebbe restituire un errore. Ad esempio, se l'attributo EmployeeID è annotato con l'annotazione id-prefix, XPath Employee[@EmployeeID=1]
genera un errore, perché EmployeeID ha l'annotazione id-prefix e non può essere convertita in number.