SQL Server 2008

Novos tipos de dados

Kelly Wilson

 

Visão geral:

  • Novos tipos de dados de data e hora
  • Posição de representação em uma hierarquia
  • Dois modelos para trabalhar com dados espaciais

A realização de negócios nessa economia globalizada exige cada vez mais das empresas o uso de novos tipos de dados, aplicativos e cálculos complexos. Os sete novos tipos de dados internos do SQL Server 2008

proporcionam meios de trabalhar e simplificar o gerenciamento de dados mais complicados.

Date e Time

Com o tipo de dados datetime antigo, os usuários do SQL Server® não tinham a possibilidade de trabalhar com informações de data e hora separadamente. Quatro dos novos tipos de dados – date, time, datetime2 e datetimeoffset – mudaram isso ao simplificar o trabalho com dados de data e hora e oferecer um intervalo de datas maior, além da precisão fracionária de segundos e do suporte a fuso horário. Os novos aplicativos de banco de dados devem usar esses novos tipos de dados em lugar do datetime herdado. Vejamos as novas versões mais detalhadamente.

O tipo de dados date armazena uma data sem um componente time. O intervalo é de 1º de janeiro de 1.000 até 31 de dezembro de 9.999 (0001-01-01 a 9999-12-31). Cada variável date exige 3 bytes para armazenamento e conta com uma precisão de 10 dígitos. A precisão do tipo de dados está limitada a um único dia.

Observe a Figura 1, que mostra como criar e inicializar variáveis Date em scripts T-SQL. A variável @myDate1 é inicializada por uma cadeia de caracteres formatada como 'MM/DD/AAAA'. A variável @myDate2 não é inicializada; ela terá um valor NULL. A variável @myDate3 é inicializada de acordo com a data de sistema do computador local. O valor das variáveis pode ser alterado a qualquer momento com as instruções SELECT ou SET, como ilustra o exemplo alterando o valor de @myDate2. As colunas de datas também podem ser criadas em tabelas. A Figura 2 mostra como criar uma tabela com três colunas de datas.

Figure 2 Create a table with three date columns

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 Create and initialize date variables in T-SQL scripts

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

O tipo de dados time armazena a hora do dia sem nenhum componente date. Como ele se baseia em um relógio com 24 horas, o intervalo suportado é 00:00:00.0000000 a 23:59:59.9999999 (horas, minutos, segundos e segundos fracionados). É possível especificar a precisão fracionária em segundos durante a criação do tipo de dados. A precisão padrão é de 7 dígitos e a exatidão, de 100 nanossegundos. A precisão afeta o espaço necessário ao armazenamento, que pode variar entre três bytes para até dois dígitos, quatro bytes para três ou quatro dígitos e cinco bytes para cinco a sete dígitos.

O script T-SQL na Figura 3 mostra como a precisão variável é afetada por conversões implícitas do valor de inicialização de uma cadeia de caracteres. O código em T-SQL primeiramente cria e inicializa oito variáveis time separadas em um valor idêntico. A precisão fracionária de cada uma das variáveis equivale ao nome. Por exemplo, @myTime3 apresenta uma precisão fracionária de três casas. Os resultados mostram que a precisão de cada tipo de dados time se equivale à precisão fracionária com a qual ela é declarada. Dígitos além do intervalo permanecem truncados.

Figure 3 Display time data type's variable precision

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

Um tipo de dados time pode ser criado como uma coluna em uma tabela. O script T-SQL DROP TABLE myTable na Figura 4 cria uma tabela chamada myTable1 e adiciona três colunas de hora à tabela. Em seguida, um registro é inserido na tabela e o conteúdo desta é exibido usando uma instrução SELECT.

Figure 4 Create 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

O tipo de dados datetimeoffset proporciona reconhecimento do fuso horário. O tipo de dados time não contém fuso horário e, assim, funciona somente de acordo com a hora local. No entanto, na economia globalizada, costuma ser necessário saber qual é a relação entre as horas em áreas diferentes do mundo. A diferença de fuso horário é indicada como + ou - hh:mm.

O código cria uma variável datetimeoffset e a inicializa de acordo com o valor time 8:52 A.M. Hora Oficial do Pacífico:

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

A cadeia de caracteres que inicializa a variável datetimeoffset (@date no script) é formatada de maneira especial, organizada do elemento mais significativo para o menos significativo. Uma única letra T maiúscula separa os elementos date e time. Um sinal de subtração separa os elementos time do fuso horário. Não há nenhum espaço entre o sinal de subtração e os elementos time ou time zone. Esse é um dos dois formatos ISO 8601 suportados pelo tipo de dados datetimeoffset. (ISO 8601 é um padrão internacional que representa valores de data e hora.)

A precisão do componente time é especificada exatamente da mesma forma que o tipo de dados time, usando os mesmos sete dígitos como padrão caso não seja especificada. O intervalo suportado é o mesmo.

O tipo de dados datetime2 é uma extensão do tipo datetime original. Ele dá suporte a um intervalo de datas maior e a mais precisão fracionária em segundos, além de lhe permitir especificar essa precisão. O intervalo de datas do tipo datetime2 é de 1º de janeiro de 1.000 até 31 de dezembro de 9.999, em comparação com o intervalo de 1º de janeiro de 1.753 até 31 de dezembro de 9.999 do datetime original. Assim como acontece com o tipo time, são fornecidos sete segundos de precisão fracionária. O tipo datetime original fornecia três dígitos de precisão e um intervalo de hora entre 00:00:00 e 23:59:59.999. Veja como criar uma variável datetime2 e inicializá-la de acordo com a data e a hora do servidor local:

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

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

A seguir, analisarei o novo tipo de dados hierarchyid. Esse tipo de dados funciona com a relação entre os elementos de dados de uma tabela, e não dados específicos de data e hora.

O tipo de dados Hierarchyid

O tipo de dados hierarchyid lhe permite estabelecer relações entre elementos de dados dentro de uma tabela, especificamente para representar uma posição em uma hierarquia. Para explorar esse tipo de dados, comecemos criando o banco de dados MyCompany e preenchendo-o com dados do funcionário por meio do script na Figura 5.

Figure 5 Create and populate the MyCompany database

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

A Figura 6 mostra o banco de dados simples resultante que consiste em uma tabela de funcionários única. Essa tabela de funcionários no banco de dados MyCompany não tem nenhuma estrutura imposta. Isso é normal para um banco de dados relacional, porque a estrutura é imposta dinamicamente por um aplicativo por meio da consulta e do código de processamento.

Figure 6 Tabela de funcionários MyCompany

Figure 6** Tabela de funcionários MyCompany **

Já os dados corporativos normalmente têm um tipo de estrutura inerente. Por exemplo, toda empresa tem uma estrutura hierárquica como, por exemplo, a mostrada para MyCompany na Figura 7. Todos os funcionários da MyCompany respondem a David, o CEO. Alguns deles respondem diretamente, como é o caso de Jill. Outros, a exemplo de Mary, respondem por meio de um intermediário. Em termos de programação, a estrutura hierárquica da MyCompany é conhecida como árvore por conta da forma a que ela se assemelha. David, no topo, não responde a ninguém; ele é o pai ou ancestral. Os funcionários que respondem a David estão abaixo dele. Esses nós são conhecidos como filhos ou descendentes. David pode ter quantos descendentes forem necessários para representar seus subordinados diretos.

Figure 7 Estrutura organizacional da MyCompany

Figure 7** Estrutura organizacional da MyCompany **(Clique na imagem para aumentar a exibição)

O script na Figura 8 recria o banco de dados MyCompany usando o tipo de dados hierarchyid, estabelecendo uma relação que corresponda à estrutura hierárquica da MyCompany. A instrução ALTER TABLE é usada para inicialmente adicionar uma coluna do tipo hierarchyid. Em seguida, o nó referente a David é inserido usando o método GetRoot de hierarchyid. Depois, os subordinados de David são adicionados à árvore por meio do método GetDescendant.

Figure 8 Rebuild the database using 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

Assim que os registros do banco de dados forem adicionados e a hierarquia for construída, o conteúdo da tabela de funcionários poderá ser exibido com uma consulta como esta:

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 é a coluna de hierarchyid. Cada caractere de barra / no resultado indica um nó na árvore hierárquica. David está na raiz, indicada por uma única barra. Sariya, John e Jill respondem a David e apresentam duas barras, o que indica serem o segundo nó da hierarquia. Os números 1, 2 ou 3 mostram a ordem do respectivo nó filho. O sistema é muito flexível. Os nós filhos podem ser removidos, inseridos ou adicionados conforme necessário. Se adicionássemos um funcionário entre John e Jill, por exemplo, ele seria listado no conjunto de resultados como: /2.1/.

Para responder à pergunta, por exemplo, "Quem responde a Sariya?", é possível criar uma consulta como mostrado no seguinte código 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/

A consulta usa o método GetAncestor de hierarchyid, que retorna o pai do nó de hierarchyid atual. No código anterior, a variável @Sariya está definida como sendo o nó da hierarquia de Sariya. Isso porque Sariya é o ancestral direto de qualquer funcionário que responda a ela. Por isso, escrever uma consulta que retorne os funcionários que respondem diretamente a Sariya consiste em recuperar o nó de Sariya da árvore e selecionar todos os funcionários cujo ancestral seja o nó referente a Sariya.

As colunas de hierarchyid tendem a ser muito compactas porque o número de bits necessários à representação de um nó em uma árvore depende do número médio de filhos no nó (normalmente conhecido como fan-out do nó). Por exemplo, um novo nó em uma hierarquia organizacional de 100 mil funcionários, com um fan-out médio de seis níveis, exigiria cerca de cinco bytes de armazenamento.

O tipo de dados hierarchyid fornece vários métodos que facilitam o trabalho com dados hierárquicos. Um resumo desses métodos é mostrado na Figura 9. Há informações detalhadas sobre todos os métodos disponíveis em SQL Server Books Online (msdn2.microsoft.com/ms130214).

Figure 9 Methods provided by the hierarchyid data type

Método Descrição
GetAncestor Retorna um hierarchyid que representa o º ancestral deste nó de hierarchyid.
GetDescendant Retorna um nó filho deste nó de hierarchyid.
GetLevel Retorna um inteiro que representa até onde se estende este nó de hierarchyid em toda a hierarquia.
GetRoot Retorna o nó de hierarchyid raiz da árvore hierárquica. Estático.
IsDescendant Retorna verdadeiro caso o nó filho passado seja um descendente deste nó de hierarchyid.
Parse Converte a representação de uma cadeia de caracteres de uma hierarquia em um valor hierárquico. Estático.
Reparent Move um nó de uma hierarquia para um novo local dentro dela.
ToString Retorna uma cadeia de caracteres que contém a representação lógica de hierarchyid.

Tipos de dados espaciais

Espaciais são dados que identificam formas e locais geográficos, essencialmente na Terra. Entre eles podem estar pontos de referência, estradas e até mesmo o local de uma empresa. O SQL Server 2008 fornece os tipos de dados geography e geometry para trabalhar com esses tipos de dados.

O tipo de dados geography trabalha com informações sobre o arredondamento da terra. O modelo de terra arredondada leva em conta a superfície curvada da terra em seus cálculos. As informações sobre a posição são fornecidas em longitude e latitude. Esse modelo é bem adequado a aplicações como transporte transoceânico, planejamento militar e de curto alcance relacionadas à superfície terrestre. Trata-se do modelo a ser usado se os dados forem armazenados em latitudes e longitudes.

O tipo de dados geometry trabalha com o modelo plano ou de achatamento da terra. Nesse modelo, a terra é tratada como uma projeção achatada começando em um ponto conhecido. Como o modelo de terra achatada não leva em conta a curvatura terrestre, ele é essencialmente usado na descrição de distâncias curtas – por exemplo, em um aplicativo de banco de dados que mapeia o interior de um edifício.

Os tipos geography e geometry são criados a partir de objetos vetoriais, especificados nos formatos WKT (Well-Known Text) ou WKB (Well-Known Binary). Esses são os formatos de transporte para dados espaciais descritos pela Especificação de recursos simples para SQL do OGC (Open Geospatial Consortium). A Figura 10 lista os sete tipos de objetos vetoriais para os quais o SQL Server 2008 dá suporte.

Figure 10 Vector objects supported by SQL Server 2008

Objeto Descrição
Point Um local.
MultiPoint Uma série de pontos.
LineString Uma série de zero ou mais pontos ligados por linhas.
MultiLineString Um conjunto de linestrings.
Polygon Uma região contígua descrita por um conjunto de linestrings fechadas.
MultiPolygon Um conjunto de polygons.
GeometryCollection Uma coleção de tipos geometry.

Para criar um tipo geography com um ou mais objetos vetoriais, você deve primeiramente declarar o tipo no script T-SQL, como mostra a Figura 11. Em seguida, você chama um dos métodos listados na Figura 12, passa a cadeia de caracteres do objeto vetorial e a SRID (Spatial Reference ID). A SRID é o sistema de identificação de referência espacial definido pelo European Petroleum Survey Group. Ela faz parte de um conjunto de padrões desenvolvidos para cartografia, pesquisa e armazenamento geodésico de dados. Cada SRID identifica um tipo específico de elipsóide a ser usado nos cálculos geográficos. Ela é necessária porque a terra não é uma esfera perfeita. O SQL Server 2008 só pode realizar cálculos usando SRIDs idênticas.

Figure 12 Construct objects for geography and geometry

Método Descrição
STGeomFromText Cria qualquer tipo de instância de geography usando o texto de entrada.
STPointFromText Cria uma instância Point de geography usando o texto de entrada.
STMPointFromText Cria uma instância MultiPoint de geography usando o texto de entrada.
STLineFromText Cria uma instância LineString de geography usando o texto de entrada.
STMLineFromText Cria uma instância MultiLineString de geography usando o texto de entrada.
STPolyFromText Cria uma instância Polygon de geography usando o texto de entrada.
STMPolyFromText Cria uma instância MultiPolygon de geography usando o texto de entrada.
STGeomCollFromText Cria uma instância GeometryCollection de geography usando o texto de entrada.

Figure 11 Create points, lines, and polygon geometry

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))

Diferenças entre geography e geometry

Como os tipos de dados geography e geometry servem para trabalhar com tipos diferentes de dados, há algumas diferenças a serem observadas. Com o tipo de dados geometry, as distâncias e as áreas recebem a mesma unidade de medida das coordenadas das instâncias. Por exemplo, a distância entre os pontos (0,0) e (6,8) será sempre de 10 unidades. Não é esse o caso com o tipo geography, que funciona com coordenadas elipsoidais expressas em graus latitudinais e longitudinais.

O tipo de dados GEOMETRY retorna resultados incoerentes quando as coordenadas são expressas como pares de latitude/longitude. O seguinte código T-SQL calcula a distância entre os pontos (90 0) e (90 180). Como ambos se referem ao Pólo Norte, a distância entre eles deve ser 0. No caso de GEOMETRY, a distância calculada é de 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

A orientação dos dados espaciais também é diferente para os dois tipos de dados. No sistema plano usado pelo tipo de dados geometry, a orientação do polígono não é um fator importante. Por exemplo, um polígono com as coordenadas ((0, 0), (10, 0), (0, 20), (0, 0)) é considerado igual ao polígono ((0, 0), (0, 20), (10, 0), (0, 0)). Porém, no modelo de dados usado pelo tipo de dados geography, um polígono permanece obscuro sem uma orientação especificada. Considere, por exemplo, um anel endocapsular. O polígono descrito por esse anel se refere ao hemisfério norte ou ao hemisfério sul? A questão aqui é que, ao trabalhar com dados geográficos, a orientação e a localização devem ser descritas com precisão.

Também há algumas restrições quanto ao tipo de dados geography do SQL Server 2008. Por exemplo, cada instância de geography deve caber em um único hemisfério. Objetos espaciais maiores não são permitidos, e eles causarão a emissão de ArgumentException. Os tipos de dados geography que exigem duas entradas retornarão NULL se os resultados dos métodos não couberem em um único hemisfério.

O SQL Server fornece vários métodos que possibilitam a realização das operações em instâncias de geography e geometry. A Figura 13 mostra alguns exemplos usando métodos fornecidos pelo SQL Server 2008 para o trabalho com dados espaciais. Por conta de restrições quanto ao espaço, não posso entrar em mais detalhes sobre esse tópico, mas é possível encontrar descrições completas em SQL Server Books Online.

Figure 13 Working with spatial data

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

Espero que essas informações sobre os sete novos tipos de dados do SQL Server 2008 tenham sido úteis.

Kelly Wilson é engenheira de software há mais de 20 anos. O nome dela aparece nos créditos de aplicativos em SQL Server, gráficos 3D, jogos e ciências das cores. Atualmente, Kelly é escritora de programação do grupo de SQL Server da Microsoft.

© 2008 Microsoft Corporation e CMP Media, LLC. Todos os direitos reservados. A reprodução parcial ou completa sem autorização é proibida..