SQL Server 2008:

nuovi tipi di dati

Kelly Wilson

 

Panoramica:

  • Nuovi tipi di dati relativi a data e ora
  • Rappresentazione della posizione in una gerarchia
  • Due modelli per l'utilizzo dei dati spaziali

La possibilità di operare con successo nell'economia globale attuale richiede sempre più l'utilizzo da parte delle aziende di nuovi tipi di dati, applicazioni e calcoli complessi. I sette nuovi tipi di dati incorporati in SQL Server 2008

consentono di lavorare con dati più complessi e di semplificarne la gestione.

Data e ora

Con il tipo di dati precedente, datetime, gli utenti di SQL Server® non avevano la possibilità di utilizzare le informazioni relative a data e ora separatamente. Quattro dei nuovi tipi di dati, date, time, datetime2 e datetimeoffset, cambiano questa situazione, semplificando l'utilizzo dei dati relativi a data e ora e fornendo maggiore supporto per l'intervallo di date, la precisione in secondi frazionari e il fuso orario. È opportuno che le nuove applicazioni di database utilizzino questi nuovi tipi di dati anziché il tipo di dati datetime precedente. Esaminiamo ora nei dettagli le nuove versioni.

Il tipo di dati date consente di archiviare una data senza un valore dell'ora. Questo tipo di dati include un intervallo compreso tra il 1 gennaio 1000 e il 31 dicembre 9999 (da 01-01-0001 a 31-12-9999). Ogni variabile relativa alla data richiede 3 byte di archiviazione e presenta una precisione di 10 cifre. L'accuratezza del tipo di data è limitata a un singolo giorno.

Dare un'occhiata alla Figura 1, in cui viene illustrato come creare e inizializzare le variabili Date negli script T-SQL. La variabile @myDate1 viene inizializzato da una stringa nel formato "MM/DD/YYYY". La variabile @myDate2 non viene inizializzata e avrà un valore NULL. La variabile @myDate3 viene inizializzata sulla data del sistema del computer locale. Il valore delle variabili può essere modificato in qualsiasi momento con le istruzioni SELECT o SET, modificando il valore di @myDate2, come illustrato nell'esempio. È inoltre possibile creare colonne di date in tabelle. Nella Figura 2 viene illustrato come creare una tabella con tre colonne di date.

Figure 2 Creazione di una tabella con tre colonne data

USE TempDB
GO

CREATE TABLE myTable
(
    myDate1 date,myDate2 date,myDate3 date
)
GO

INSERT INTO myTable
VALUES('01/22/2005',
       '2007-05-08 12:35:29.1234567 +12:15',
       GetDate())

SELECT * FROM myTable

--Results
--myDate1    myDate2    myDate3
------------ ---------- ----------
--2005-01-22 2007-05-08 2007-11-20

Figure 1 Creazione e inizializzazione delle variabili del tipo di dati date in script T-SQL

DECLARE @myDate1 date = '01/22/2005'
DECLARE @myDate2 date
DECLARE @myDate3 date = GetDate()

SELECT @myDate2 = '2007-05-08 12:35:29.1234567 +12:15'

SELECT @myDate1 AS '@myDate1',
       @myDate2 AS '@myDate2',
       @myDate3 AS '@myDate3'

--Results
--@myDate1   @myDate2   @myDate3
------------ ---------- ----------
--2005-01-22 2007-05-08 2007-11-20

Il tipo di dati time archivia l'ora del giorno senza alcun valore di data. È basato sul formato a 24 ore e, pertanto, supporta un intervallo compreso tra 00:00:00.0000000 e 23:59:59.9999999 (ore, minuti, secondi e secondi frazionari). È possibile specificare la precisione in secondi frazionari durante la creazione del tipo di dati. La precisione predefinita è 7 cifre; l'accuratezza è di 100 nanosecondi. La precisione influisce sulla quantità di spazio di archiviazione necessaria, che può essere di 3 byte per un massimo di 2 cifre, 4 byte per 3 o 4 cifre e 5 byte per un intervallo di cifre compreso tra 5 e 7.

Nello script T-SQL nella Figura 3 viene illustrato come la precisione della variabile sia influenzata da conversioni implicite di un valore di inizializzazione di una stringa. Nel codice T-SQL vengono create otto variabili time separate che vengono inizializzate su un valore identico. La precisione frazionaria di ciascuna variabile è equivalente al relativo nome. Ad esempio, @myTime3 ha una precisione frazionaria di tre posizioni decimali. I risultati mostrano che la precisione di ciascun tipo di dati time è equivalente alla precisione frazionaria con cui viene dichiarato. Le cifre che non rientrano nell'intervallo vengono troncate.

Figure 3 Visualizzazione della precisione della variabile del tipo di dati time

DECLARE @myTime  time = '01:01:01.1234567 +01:01'
DECLARE @myTime1 time(1) = '01:01:01.1234567 +01:01'
DECLARE @myTime2 time(2) = '01:01:01.1234567 +01:01'
DECLARE @myTime3 time(3) = '01:01:01.1234567 +01:01'
DECLARE @myTime4 time(4) = '01:01:01.1234567 +01:01'
DECLARE @myTime5 time(5) = '01:01:01.1234567 +01:01'
DECLARE @myTime6 time(6) = '01:01:01.1234567 +01:01'
DECLARE @myTime7 time(7) = '01:01:01.1234567 +01:01'

SELECT @myTime  AS '@myTime',
       @myTime1 AS '@myTime1',
       @myTime2 AS '@myTime2',
       @myTime3 AS '@myTime3',
       @myTime4 AS '@myTime4',
       @myTime5 AS '@myTime5',
       @myTime6 AS '@myTime6',
       @myTime7 AS '@myTime7'

--Results
--@myTime          @myTime1   @myTime2    @myTime3     @myTime4      
------------------ ---------- ----------- ------------ -------------
--01:01:01.1234567 01:01:01.1 01:01:01.12 01:01:01.123 01:01:01.1235
--
--@myTime5       @myTime6        @myTime7
---------------- --------------- ----------------
--01:01:01.12346 01:01:01.123457 01:01:01.1234567

DROP TABLE myTable

Un tipo di dati time può essere creato come colonna in una tabella. Nello script T-SQL DROP TABLE myTable nella Figura 4 viene creata una tabella denominata myTable1 a cui vengono aggiunte tre colonne ora. Nella tabella viene quindi inserito un record e il contenuto della tabella viene visualizzato con un'istruzione SELECT.

Figure 4 Creazione di myTable1

USE TempDB
GO

CREATE TABLE myTable1
(
    myTime1 time(1),
    myTime2 time(2),
    myTime3 time(3)
)
GO

INSERT INTO myTable1
VALUES('01:30:01.1234567',
       '02:34:01.1234567',
       '03:01:59.1234567')

SELECT * from myTable1

--Results
--myTime1    myTime2     myTime3
------------ ----------- ------------
--01:30:01.1000000 02:34:15.1200000 03:01:59.1230000

DROP TABLE myTable1

Datetimeoffset e Datetime2

Il tipo di dati datetimeoffset contiene informazioni sul fuso orario. Il tipo di dati time non contiene alcun fuso orario e prevede solo l'utilizzo dell'ora locale. Nell'economia globale, tuttavia, è spesso necessario essere informati sulla differenza di diversi fusi tra le diverse località del mondo. L'offset dei fusi orari è rappresentato in formato + o - hh:mm.

Nel seguente codice viene creata una variabile datetimeoffset che viene inizializzata sul valore di ora 8:52 (fuso orario del Pacifico):

DECLARE @date DATETIMEOFFSET = '2007-11-26T08:52:00.1234567-08:00'
PRINT @date
--Results
--2007-11-26 08:52:00.1234567 -08:00

La stringa che inizializza la variabile datetimeoffset (@date nello script) presenta un formato speciale, in cui gli elementi vengono ordinati a partire dal più significativo fino al meno significativo. Una singola lettera T in maiuscolo separa gli elementi relativi a data e ora. Un segno meno (-) separa gli elementi relativi all'ora dal fuso orario. Non ci sono spazi tra il segno meno e gli elementi relativi a ora o fuso orario. Questo formato corrisponde a uno dei due formati ISO 8601 supportati dal tipo di dati datetimeoffset. ISO 8601 è uno standard internazionale per la rappresentazione di valori relativi a data e ora.

La precisione del componente ora viene specificata allo stesso modo del tipo di dati time e utilizza come impostazione predefinita le stesse sette cifre, se non specificata. L'intervallo supportato è identico.

Il tipo di dati datetime2 è un'estensione del tipo di dati datetime originale. Supporta un intervallo di date più grande e una maggiore precisione in secondi frazionari, che può essere definita dall'utente. L'intervallo di date del tipo datetime2 è compreso tra il 1 gennaio 0001 e il 31 dicembre 9999, mentre il tipo datetime precedente supportava un intervallo compreso tra il 1 gennaio 1753 e il 31 dicembre 9999. Allo stesso modo del tipo time, questo tipo di dati fornisce una precisione di sette secondi frazionari. Il tipo datetime originale forniva una precisione di tre cifre e supportava un intervallo di ore compresso tra 00:00:00 e 23:59:59.999. Di seguito viene illustrato come creare una variabile datetime2 e come inizializzarla sulla data e l'ora del server locale:

DECLARE @datetime2 DATETIME2 = GetDate();
PRINT @datetime2

--Results
--2007-11-26 09:39:04.1370000

Nella sezione successiva verrà esaminato il nuovo tipo di dati hierarchyid. Questo tipo di dati supporta la relazione tra gli elementi di dati all'interno di una tabella, anziché uno specifico elemento di dati relativo a data o ora.

Tipo di dati hierarchyid

Il tipo di dati hierarchyid consente di creare delle relazioni tra gli elementi di dati all'interno di una tabella, appositamente per rappresentare una posizione in una gerarchia. Per esplorare questo tipo di dati, creare innanzitutto il database MyCompany e compilarlo con i dati relativi ai dipendenti, utilizzando lo script nella Figura 5.

Figure 5 Creazione e compilazione del database MyCompany

USE MASTER
GO

CREATE DATABASE MyCompany
GO
USE MyCompany
GO

--Create a table called employee that will store
--the data for the employees for MyCompany.
    
CREATE TABLE employee
(
    EmployeeID int NOT NULL,
    EmpName    varchar(20) NOT NULL,
    Title      varchar(20) NULL,
    Salary     decimal(18, 2) NOT NULL,
    hireDate   datetimeoffset(0) NOT NULL,
)
GO

--These statements will insert the data for the employees of MyCompany.

INSERT INTO employee
VALUES(6,   'David',  'CEO', 35900.00, '2000-05-23T08:30:00-08:00')

INSERT INTO employee
VALUES(46,  'Sariya', 'Specialist', 14000.00, '2002-05-23T09:00:00-08:00')

INSERT INTO employee
VALUES(271, 'John',   'Specialist', 14000.00, '2002-05-23T09:00:00-08:00')

INSERT INTO employee
VALUES(119, 'Jill',   'Specialist', 14000.00, '2007-05-23T09:00:00-08:00')

INSERT INTO employee
VALUES(269, 'Wanida', 'Assistant', 8000.00, '2003-05-23T09:00:00-08:00')

INSERT INTO employee
VALUES(272, 'Mary',   'Assistant', 8000.00, '2004-05-23T09:00:00-08:00')
GO
--Results
--EmployeeID  EmpName Title      Salary   hireDate
------------- ------- ---------- -------- --------------------------
--6           David   CEO        35900.00 2000-05-23 08:30:00 -08:00
--46          Sariya  Specialist 14000.00 2002-05-23 09:00:00 -08:00
--271         John    Specialist 14000.00 2002-05-23 09:00:00 -08:00
--119         Jill    Specialist 14000.00 2007-05-23 09:00:00 -08:00
--269         Wanida  Assistant  8000.00  2003-05-23 09:00:00 -08:00
--272         Mary    Assistant  8000.00  2004-05-23 09:00:00 -08:00

Nella Figura 6 viene illustrato il semplice database risultante, composto da una singola tabella di dipendenti. Questa tabella di dipendente nel database MyCompany non presenta alcuna struttura imposta. Questo è normale per un database relazionale, in quanto la struttura viene imposta in modo dinamico da un'applicazione tramite il relativo codice di query e di elaborazione.

Figura 6 Tabella dei dipendenti del database MyCompany

Figura 6** Tabella dei dipendenti del database MyCompany **

I dati aziendali, tuttavia, presentano in genere un tipo di struttura intrinseca. Ad esempio, ogni azienda prevede una struttura di reporting, come quella mostrata per MyCompany nella Figura 7. Tutti i dipendenti di MyCompany fanno riferimento a David, il CEO. Alcuni dipendenti riferiscono direttamente, come nel caso di Jill. Altri, come Mary, riferiscono attraverso un intermediario. In termini di programmazione, la struttura di reporting per MyCompany viene definita albero in quanto presenta una forma simile a un albero. David, in cima alla struttura, non riferisce a nessuno ed è l'elemento padre o predecessore. I dipendenti che riferiscono a David sono sotto. Tali nodi vengono definiti elementi figlio o discendenti. David può avere il numero di discendenti necessario per rappresentare i relativi report diretti.

Figura 7 Struttura organizzativa di MyCompany

Figura 7** Struttura organizzativa di MyCompany **(Fare clic sull'immagine per ingrandirla)

Nello script nella Figura 8 viene ricreato il database MyCompany mediante il tipo di dati hierarchyid, creando una relazione che corrisponde alla struttura di reporting per MyCompany. l'istruzione ALTER TABLE viene utilizzata per aggiungere una colonna di tipo hierarchyid. Il nodo di David viene quindi inserito utilizzando il metodo GetRoot di hierarchyid. I dipendenti che riferiscono direttamente a David vengono aggiunti all'albero utilizzando il metodo GetDescendant.

Figure 8 Rigenerazione del database mediante hierarchyid

DELETE employee
GO
ALTER TABLE employee ADD OrgNode hierarchyid NOT NULL
GO

DECLARE @child hierarchyid,
@Manager hierarchyid = hierarchyid::GetRoot()

--The first step is to add the node at the top of the
--tree. Since David is the CEO his node will be the
--root node.

INSERT INTO employee
VALUES(6,   'David',  'CEO', 35900.00,
       '2000-05-23T08:30:00-08:00', @Manager)

--The next step is to insert the records for
--the employees that report directly to David.

SELECT @child = @Manager.GetDescendant(NULL, NULL)

INSERT INTO employee
VALUES(46,  'Sariya', 'Specialist', 14000.00,
       '2002-05-23T09:00:00-08:00', @child)

SELECT @child = @Manager.GetDescendant(@child, NULL)
INSERT INTO employee
VALUES(271, ‚John',   ‚Specialist', 14000.00,
       '2002-05-23T09:00:00-08:00', @child)

SELECT @child = @Manager.GetDescendant(@child, NULL)
INSERT INTO employee
VALUES(119, ‚Jill',   ‚Specialist', 14000.00,
       ‚2007-05-23T09:00:00-08:00', @child)

--We can now insert the employee that reports to
--Sariya.
SELECT @manager = OrgNode.GetDescendant(NULL, NULL)
FROM employee WHERE EmployeeID = 46

INSERT INTO employee
VALUES(269, ‚Wanida', ‚Assistant', 8000.00,
       ‚2003-05-23T09:00:00-08:00', @manager)

--Next insert the employee that report to John.
SELECT @manager = OrgNode.GetDescendant(NULL, NULL)
FROM employee WHERE EmployeeID = 271

INSERT INTO employee
VALUES(272, ‚Mary',   ‚Assistant', 8000.00,
       ‚2004-05-23T09:00:00-08:00', @manager)
GO

Dopo aver aggiunto i record del database e dopo aver creato la gerarchia, il contenuto della tabella dei dipendenti può essere visualizzato con la seguente query:

SELECT EmpName, Title, Salary, OrgNode.ToString() AS OrgNode
FROM employee ORDER BY OrgNode
GO
--Results
--EmpName  Title      Salary    OrgNode
---------- ---------- --------- -------
--David    CEO        35900.00  /
--Sariya   Specialist 14000.00  /1/
--Wanida   Assistant  8000.00   /1/1/
--John     Specialist 14000.00  /2/
--Mary     Assistant  8000.00   /2/1/
--Jill     Specialist 14000.00  /3/

OrgNode è la colonna hierarchyid. Ciascuna barra (/) nel risultato indica un nodo nell'albero gerarchico. David è al livello radice, che viene rappresentato con una singola barra. Sariya, John e Jill riferiscono a David e sono contrassegnati da due barre, che indicano che essi rappresentano il secondo nodo della gerarchia. I numeri 1, 2 e 3 indicano l'ordine del rispettivo nodo figlio. Questo sistema è molto flessibile. I nodi figlio possono essere rimossi, inseriti o aggiunti in base alle esigenze. Se si aggiungesse un dipendente tra John e Jill, ad esempio, tale dipendente verrebbe elencato nel set di risultati come indicato di seguito: /2.1/.

Per rispondere alla domanda, ad esempio, "Chi riferisce a Sariya?", è possibile creare una query come illustrato nel seguente codice T-SQL:

DECLARE @Sariya hierarchyid

SELECT @Sariya = OrgNode
FROM employee WHERE EmployeeID = 46

SELECT EmpName, Title, Salary, OrgNode.ToString() AS 'OrgNode'
FROM employee
WHERE OrgNode.GetAncestor(1) = @Sariya
GO
--Results
--EmpName Title     Salary  OrgNode
--------- --------- ------- -------
--Wanida  Assistant 8000.00 /1/1/

La query utilizza il metodo GetAncestor di hierarchyid, che restituisce il nodo padre del nodo hierarchyid corrente. Nel codice precedente, la variabile @Sariya è impostata sul nodo della gerarchia relativo a Sariya. Questo avviene perché Sariya è il predecessore diretto di qualunque dipendente ai suoi ordini. Pertanto, la scrittura di una query che restituisce i dipendenti che riferiscono direttamente a Sariya prevede il recupero del nodo di Sariya dall'albero e la selezione di tutti i dipendenti il cui nodo predecessore corrisponde al nodo di Sariya.

Le colonne di hierarchyid sono molto compatte, in quanto il numero di bit necessari per rappresentare un nodo in un albero dipende dal numero medio degli elementi figlio per il nodo (in genere definito fanout del nodo). Ad esempio, un nuovo nodo in una gerarchia organizzativa di 100.000 dipendenti, con un fanout medio di sei livelli, richiederebbe circa cinque byte di spazio di archiviazione.

Il tipo di dati hierarchyid fornisce diversi metodi che semplificano l'utilizzo dei dati gerarchici. Un riepilogo di questi metodi è illustrato nella Figura 9. Informazioni dettagliate su tutti i metodi sono disponibili nella documentazioni in linea di SQL Server (msdn2.microsoft.com/ms130214).

Figure 9 Metodi forniti dal tipo di dati hierarchyid

Metodo Descrizione
GetAncestor Restituisce un tipo hierarchyid che rappresenta il predecessore n del nodo hierarchyid corrente.
GetDescendant Restituisce un nodo figlio del nodo hierarchyid corrente.
GetLevel Restituisce un numero intero che rappresenta la profondità del nodo hierarchyid corrente nella gerarchia globale.
GetRoot Restituisce il nodo hierarchyid radice dell'albero gerarchico corrente. Tipo statico.
IsDescendant Restituisce true se il nodo figlio passato è un discendente del nodo hierarchyid corrente.
Parse Converte una rappresentazione stringa di una gerarchia in un valore hierarchyid. Tipo statico.
Reparent Sposta un nodo di una gerarchia in una nuova posizione all'interno della gerarchia.
ToString Restituisce una stringa che contiene la rappresentazione logica del tipo hierarchyid corrente.

Tipi di dati spaziali

I dati spaziali sono dati che identificano forme e posizioni geografiche, principalmente sul pianeta Terra. Questi dati possono includere punti di riferimento, strade e persino la sede di un'azienda. Per consentire l'utilizzo di questo tipo di dati, in SQL Server 2008 vengono forniti dati di tipo geografico e di tipo geometrico.

I dati di tipo geografico prevedono l'utilizzo di soluzioni Round Earth. Il modello Round Earth prende in considerazione nei relativi calcoli la superficie curva della Terra. Le informazioni di posizione vengono fornite in longitudine e in latitudine. Questo modello risulta appropriato per applicazioni come spedizioni transoceaniche, pianificazione militare e applicazioni a breve raggio correlate al territorio geografico. Questo è il modello da utilizzare se i dati vengono memorizzati in termini di latitudine e longitudine.

I dati di tipo geometrico funzionano con il modello planare o Flat Earth. In questo modello, la Terra viene considerata come una proiezione piatta che ha inizio in un punto noto. Il modello Flat Earth non prende in considerazione la curvatura della terra e, pertanto, viene utilizzato principalmente per descrivere brevi distanze, ad esempio in un un'applicazione di database che esegue il mapping delle aree interne di un edificio.

I dati di tipo geografico e geometrico vengono creati da oggetti vettoriali, specificati in formato WKT (Well-Known Text) o WKB (Well-Known Binary). Questi sono formati di trasporto per i dati spaziali descritti dalla specifica Simple Features for SQL dell'Open Geospatial Consortium (OGC). Nella Figura 10 vengono elencati i sette tipi di oggetti vettoriali supportati da SQL Server 2008.

Figure 10 Oggetti vettoriali supportati da SQL Server 2008

Oggetto Descrizione
Point Una posizione.
MultiPoint Una serie di punti.
LineString Una serie di zero o più punti collegati da linee.
MultiLineString Una serie di oggetti linestring.
Polygon Una regione contigua descritta da una serie di oggetti linestring chiusi.
MultiPolygon Una serie di poligoni.
GeometryCollection Un insieme di tipi geometrici.

Per creare dati di tipo geografico con uno o più oggetti vettoriali, dichiarare prima il tipo geografico nello script T-SQL, come illustrato nella Figura 11. Chiamare quindi uno dei metodi riportati nella Figura 12 e passare la stringa di caratteri per l'oggetto vettoriale e il sistema SRID (Spatial Reference ID). SRID è il sistema di identificazione di riferimento spaziale, definito dall'European Petroleum Survey Group. Fa parte di una serie di standard sviluppati per la cartografia, l'analisi e l'archiviazione dei dati geodetici. Ogni SRID identifica un tipo specifico di ellissoide da utilizzare nei calcoli geografici. Questo è necessario in quanto la terra non è una sfera perfetta. SQL Server 2008 è in grado di eseguire solo calcoli su SRID identici.

Figure 12 Creazione di oggetti per la geografia e la geometria

Metodo Descrizione
STGeomFromText Crea qualsiasi tipo di istanza geografica dal testo di input.
STPointFromText Crea un'istanza Point di tipo geografico dal testo di input.
STMPointFromText Crea un'istanza MultiPoint di tipo geografico dal testo di input.
STLineFromText Crea un'istanza LineString di tipo geografico dal testo di input.
STMLineFromText Crea un'istanza MultiLineString di tipo geografico dal testo di input.
STPolyFromText Crea un'istanza Polygon di tipo geografico dal testo di input.
STMPolyFromText Crea un'istanza MultiPolygon di tipo geografico dal testo di input.
STGeomCollFromText Crea un'istanza Geometry­Collection di tipo geografico dal testo di input.

Figure 11 Creazione di punti, di linee e della geometria del poligono

DECLARE @geo1 geometry
SELECT @geo1 = geometry::STGeomFromText('POINT (3 4)', 0)
PRINT @geo1.ToString()

DECLARE @geo2 geometry
SELECT @geo2 = geometry::Parse('POINT(3 4 7 2.5)')
PRINT @geo2.STX;
PRINT @geo2.STY;
PRINT @geo2.Z;
PRINT @geo2.M;

DECLARE @geo3 geography;
SELECT @geo3 = geography::STGeomFromText(
    'LINESTRING(47.656 -122.360, 47.656 -122.343)', 4326);
SELECT @geo3.ToString();

--Results
--POINT (3 4)
--3
--4
--7
--2.5

DECLARE @gx geometry; 
SET @gx = geometry::STPolyFromText(
    'POLYGON ((5 5, 10 5, 10 10, 5 5))', 0);
PRINT @gx.ToString();
--Results
--POLYGON ((5 5, 10 5, 10 10, 5 5))

Differenze tra i dati di tipo geografico e di tipo geometrico

I dati di tipo geografico e geometrico sono stati progettati per l'utilizzo di diversi tipi di dati; è necessario pertanto tenere presenti alcune differenze importanti. Con i dati di tipo geometrico, i valori delle distanze e delle aree vengono forniti nella stessa unità di misura delle coordinate delle istanze. Ad esempio, la distanza tra i punti (0.0) e (6.8) sarà sempre pari a 10 unità. Questo non avviene con i dati di tipo geografico, che prevedono l'utilizzo di coordinate ellissoidali che vengono espresse in gradi di latitudine e longitudine.

Il tipo di dati GEOMETRY restituisce risultati incoerenti quando le coordinate vengono espresse come coppie latitudine/longitudine. Nel seguente codice T-SQL viene calcolata la distanza tra POINTS (90 0) e (90 180). Entrambi questi punti fanno riferimento al Polo Nord e, pertanto, la distanza tra loro dovrebbe essere pari a 0. Nel caso del tipo GEOMETRY la distanza calcolata è pari a 180.

DECLARE @g1 GEOMETRY, @g2 GEOMETRY, @g3 GEOGRAPHY, @g4 GEOGRAPHY
SELECT @g1 = GEOMETRY::STGeomFromText('POINT (90 0)', 0)
SELECT @g2 = GEOMETRY::STGeomFromText('POINT (90 180)', 0)

SELECT @g3 = GEOGRAPHY::STGeomFromText('POINT (90 0)', 4326)
SELECT @g4 = GEOGRAPHY::STGeomFromText('POINT (90 180)', 4326)
SELECT @g2.STDistance(@g1) AS 'GEOMETRY',
       @g4.STDistance(@g3) AS 'GEOGRAPHY';

--Results
--GEOMETRY               GEOGRAPHY
------------------------ ----------------------
--180                    0

Anche l'orientamento dei dati spaziali è diverso per i due tipi di dati. Nel sistema planare utilizzato dai dati di tipo geometrico, l'orientamento del poligono non è un fattore importante. Ad esempio, un poligono con le coordinate ((0, 0), (10, 0), (0, 20), (0, 0)) viene considerato identico al poligono ((0, 0), (0, 20), (10, 0), (0, 0)). Tuttavia, nel modello di dati utilizzato dai dati di tipo geografico, un poligono non è ben definito se non ne viene specificato l'orientamento. Considerare, ad esempio, un anello intorno all'equatore. Il poligono descritto da questo anello fa riferimento all'emisfero settentrionale o meridionale? Il punto importante da considerare è che quando si utilizzando dati di tipo geografico, l'orientamento e la posizione devono essere descritti in modo accurato.

Esistono alcune restrizioni per i dati di tipo geografico in SQL Server 2008. Ad esempio, ogni istanza geografica deve rientrare in un singolo emisfero. Gli oggetti spaziali di maggiori dimensioni non sono consentiti e causano la generazione di un'eccezione ArgumentException. I dati di tipo geografico che richiedono due input restituiranno NULL se i risultati del metodo non possono essere inseriti in un singolo emisfero.

SQL Server fornisce diversi metodi che consentono l'esecuzione di operazioni su istanze geografiche e geometriche. Nella Figura 13 vengono illustrati alcuni esempi di utilizzo dei metodi forniti in SQL Server 2008 per lavorare con i dati spaziali. A causa dei limiti di spazio, questo argomento non verrà illustrato nei dettagli nel presente articolo, ma è possibile ottenere descrizioni complete in merito nella documentazione in linea di SQL Server.

Figure 13 Utilizzo di dati spaziali

DECLARE @gm geometry;
DECLARE @gg geography;
DECLARE @h geography;

SET @gm = geometry::STGeomFromText('POLYGON((0 0, 13 0, 3 3, 0 13, 0 0),(2 2, 2 1, 1 1, 1 2, 2 2))', 0);
SELECT @gm.STArea();

--Results
--38

SET @gg = geography::STGeomFromText('LINESTRING(0 0, 5 5)', 4326);
--Calculate the distance to a point slightly offset from the LINESTRING.
SET @h = geography::STGeomFromText('POINT(4 4)', 4326);
SELECT @gg.STDistance(@h);

--Results
-- 430.182777043046

--Calculate the distance to a point on the LINESTRING.
SET @h = geography::STGeomFromText('POINT(5 5)', 4326);
SELECT @gg.STDistance(@h);

--Results
-- 0

DECLARE @temp table ([name] varchar(10), [geom] geography);

INSERT INTO @temp values ('Point', geography::STGeomFromText('POINT(
5 10)', 4326));
INSERT INTO @temp values ('LineString', geography::STGeomFromText(
'LINESTRING(13 5, 50 25)', 4326));
--Calculate the distance to a point on the LINESTRING.
--Display the number of dimensions for a geography object stored in a --table variable.
INSERT INTO @temp values ('Polygon', geography::STGeomFromText(
'POLYGON((47.653 -122.358, 47.649 -122.348, 47.658 -122.348, 47.658 -122.358, 47.653 -122.358))', 4326));

SELECT [name], [geom].STDimension() as [dim]
FROM @temp;

--Results
--name       dim
------------ -----------
--Point      0
--LineString 1
--Polygon    2

Mi auguro che queste informazioni sui sette nuovi tipi di dati disponibili in SQL Server 2008 siano state utili.

Kelly Wilson vanta oltre 20 anni di esperienza nel settore della progettazione software. I suoi crediti includono applicazioni in SQL Server, grafica 3D, giochi e scienza del colore. Kelly è attualmente Programming Writer nel gruppo SQL Server di Microsoft.

© 2008 Microsoft Corporation e CMP Media, LLC. Tutti i diritti riservati. È vietata la riproduzione completa o parziale senza autorizzazione.