SQL Server 2008

新しいデータ型

Kelly Wilson

 

概要:

  • 新しい日付および時刻データ型
  • 階層内の位置を表現する
  • 空間データの操作に使用される 2 つのモデル

経済がグローバル化した今日、企業のビジネスでは、新しい種類のデータ、アプリケーション、および複雑な計算を使用する必要性がますます高まっています。SQL Server 2008 に組み込まれている 7 つの新しいデータ型を使用すると、

より複雑なデータを操作できるだけでなく、これらのデータを容易に管理できるようになります。

date と time

従来の datetime データ型では、SQL Server® ユーザーは日付と時刻の情報を別々に操作することはできませんでした。現在は、date、time、datetime2、および datetimeoffset という 4 つの新しいデータ型によってこの状況が変わり、日付と時刻のデータを容易に操作できるようになりました。また、これらのデータ型では、日付の範囲、秒の小数部分の有効桁数、およびタイム ゾーンのサポートが強化されています。新しいデータベース アプリケーションでは、従来の datetime ではなくこれらの新しいデータ型を使用することをお勧めします。では、これらのデータ型について詳しく見ていきましょう。

date データ型には、時刻要素を除いた日付が格納されます。日付の範囲は、1000 年 1 月 1 日 (0001-01-01) から 9999 年 12 月 31 日 (9999-12-31) までです。date 型の各変数は 3 バイトの領域を必要とし、有効桁数は 10 桁です。このデータ型の精度は 1 日に制限されています。

図 1 は、T-SQL スクリプトで date 型の変数を作成および初期化する方法を示しています。変数 @myDate1 は、'MM/DD/YYYY' という形式の文字列によって初期化されています。変数 @myDate2 は初期化されていないので、値は NULL になります。変数 @myDate3 は、ローカル コンピュータ システムの日付に初期化されています。変数の値は、SELECT ステートメントまたは SET ステートメントを使用していつでも変更することができます。この例では、@myDate2 の値を変更しています。また、テーブル内に date 型の列を作成することもできます。図 2 は、3 つの date 型の列が含まれたテーブルの作成方法を示しています。

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

time データ型には、日付要素を除いた時刻が格納されます。この時刻は 24 時間形式に基づいているので、サポートされる範囲は 00:00:00.0000000 ~ 23:59:59.9999999 (時間、分、秒、秒の小数部分) です。秒の小数部分の有効桁数は、データ型の作成時に指定できます。既定の有効桁数は 7 桁で、精度は 100 ナノ秒です。有効桁数は、必要な領域のサイズに影響します。2 桁の場合は 3 バイト、3 桁または 4 桁の場合は 4 バイト、5 ~ 7 桁の場合は 5 バイトがそれぞれ必要です。

図 3 の T-SQL スクリプトは、初期化に使用した文字列の値が暗黙的に変換されることによって、変数の有効桁数がどのような影響を受けるかを示しています。この T-SQL コードでは、まず 8 個の異なる time 型の変数を作成し、これらをまったく同じ値に初期化しています。各変数の小数部分の有効桁数は、変数名に含まれている数字と等しくなっています。たとえば、@myTime3 の小数部分の有効桁数は 3 桁です。結果からわかるとおり、各 time データ型の有効桁数は、宣言時に指定した小数部分の有効桁数と等しくなっています。有効桁数を超える範囲の値は切り捨てられます。

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

time データ型は、テーブル内の列として作成することができます。DROP TABLE myTable を使用する図 4 の T-SQL スクリプトでは、まず myTable1 というテーブルを作成し、このテーブルに time 型の列を 3 つ追加しています。その後、1 つのレコードをテーブルに追加し、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 と datetime2

datetimeoffset データ型は、タイム ゾーンに対応しています。タイム ゾーンを含まない time データ型で操作できるのはローカル時間のみですが、経済がグローバル化した今日では、ある地域の時刻と他の地域の時刻の関連性を把握しなければならない状況が頻繁に発生します。タイム ゾーンのオフセットは、+ hh:mm または - hh:mm で表されます。

次のコードは、datetimeoffset 型の変数を作成し、その変数の値を太平洋標準時の午前 8 時 52 分に初期化しています。

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

datetimeoffset 型の変数 (スクリプト内の @date) を初期化する文字列は特殊な形式で記述されており、最上位要素から順番に並んでいます。大文字の T を境に日付要素と時刻要素が分かれており、マイナス記号 (-) を境に時刻要素とタイム ゾーン要素が分かれています。マイナス記号と時刻要素、およびマイナス記号とタイム ゾーン要素の間にスペースはありません。この形式は、datetimeoffset データ型でサポートされている 2 つの ISO 8601 形式のうちの 1 つです (ISO 8601 は、日付値と時刻値の表現に関する国際標準です)。

時刻要素の有効桁数は、time データ型と同じ形式で指定します。指定しなかった場合は、既定の 7 桁になります。サポートされる範囲も、time データ型と同じです。

datetime2 データ型は、datetime 型を拡張した型です。この型では、表現できる日付の範囲と秒の小数部分の有効桁数が強化されています。また、有効桁数を指定することもできます。datetime2 型で表現できる日付の範囲は、1 年 1 月 1 日から 9999 年 12 月 31 日までです。これに対し、datetime 型で表現できる日付の範囲は、1753 年 1 月 1 日から 9999 年 12 月 31 日までです。time 型と同様、秒の小数部分の有効桁数は 7 桁です。datetime 型の有効桁数は 3 桁、時刻の範囲は 0 時 0 分 0 秒から 23 時 59 分 59.999 秒です。次のコードでは、datetime2 型の変数を作成し、その変数の値をローカル サーバーの日付と時刻に初期化しています。

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

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

次に、新しい hierarchyid データ型について説明します。このデータ型は、特定の日付や時刻に関するデータではなく、テーブル内のデータ要素間の関係を表します。

hierarchyid データ型

hierarchyid データ型を使用すると、テーブル内のデータ要素間の関係を構築して、階層内の位置を明確に表すことができます。このデータ型について説明するために、まず図 5 のようなスクリプトを使用して、MyCompany データベースを作成し、従業員に関するデータを格納します。

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

図 6 は、このスクリプトの結果として作成された、1 つの従業員テーブルから成る単純なデータベースを示しています。この MyCompany データベースの従業員テーブルには、構造が指定されていません。リレーショナル データベースの場合は、アプリケーションのクエリや処理コードによって構造が動的に指定されるので、このままで問題ありません。

Figure 6 MyCompany の従業員テーブル

Figure 6** MyCompany の従業員テーブル **

ただし一般に、ビジネス データには特有の構造が存在します。たとえば、どのような企業でも報告構造が存在します。図 7 は、MyCompany の報告構造を示しています。MyCompany のすべての従業員は、CEO である David に報告を行います。Jill のように直接報告を行う従業員もいれば、Mary のように他の従業員を経由して報告を行う従業員もいます。プログラミング用語で言うと、MyCompany の報告構造は、その形からツリー構造と呼ばれます。最上位の David は報告する相手が存在せず、親または先祖と呼ばれます。David に報告を行う従業員は、階層内で David より下のノードに位置します。これらのノードは、子または子孫と呼ばれます。David が直接報告を受ける子孫の数に制限はありません。

Figure 7 MyCompany の組織構造

Figure 7** MyCompany の組織構造 **(画像を拡大するには、ここをクリックします)

図 8 のスクリプトでは、hierarchyid データ型を使用して MyCompany データベースを再作成し、MyCompany の報告構造と一致する関係を構築しています。まず ALTER TABLE ステートメントを使用して、hierarchyid 型の列を追加します。次に hierarchyid 型の GetRoot メソッドを使用して David のノードを挿入します。その後、GetDescendant メソッドを使用して、David に直接報告を行う従業員をツリーに追加します。

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

データベースにレコードを追加し、階層を構築したら、次のクエリを使用して、従業員テーブルの内容を表示することができます。

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 は hierarchyid 型の列です。結果として表示される文字列のスラッシュ (/) は、階層ツリー内のノードを示しています。ルートの David は 1 つのスラッシュで表されています。David に直接報告を行う Sariya、John、および Jill は 2 つのスラッシュで表されており、階層内の上から 2 番目のノードであることを示しています。数字 1、2、3 は各子ノードの順番を示しています。このシステムの柔軟性はそれほど高くありません。子ノードは必要に応じて削除、挿入、または追加できます。たとえば、John と Jill の間に従業員を追加した場合、その従業員は結果セット内で /2.1/ として表されます。

Sariya に報告を行う従業員を参照するには、次の 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/

このクエリでは、hierarchyid 型の GetAncestor メソッドを使用して、現在の hierarchyid 型ノードの親を返しています。上記のコードでは、変数 @Sariya に階層内の Sariya のノードが設定されています。これは、Sariya に報告を行う従業員の直接の先祖が Sariya だからです。したがって、Sariya に直接報告を行う従業員を返すクエリでは、ツリーから Sariya のノードを取得した後、先祖ノードが Sariya のノードであるすべての従業員を選択します。

ツリー内のノードを表現するために必要な領域のサイズは、ノードの子の数 (よくノードのファンアウトと呼ばれます) の平均によって決まるので、hierarchyid 型の列は小規模になる傾向があります。たとえば、100,000 人の従業員が所属する組織で構成している階層のファンアウトの平均が 6 である場合、新しいノードを作成するには約 5 バイトの領域が必要です。

hierarchyid データ型では、階層データを容易に操作できるいくつかのメソッドが提供されます。図 9 は、これらのメソッドの概要を示しています。すべてのメソッドの詳細については、SQL Server オンライン ブック (msdn2.microsoft.com/ms130214) を参照してください。

Figure 9 Methods provided by the hierarchyid data type

メソッド 説明
GetAncestor この hierarchyid 型ノードの n 番目の先祖を表す hierarchyid 型ノードを返します。
GetDescendant この hierarchyid 型ノードの子ノードを返します。
GetLevel 階層全体におけるこの hierarchyid 型ノードの深さを表す整数を返します。
GetRoot この階層ツリーのルートである hierarchyid 型ノードを返します (静的メソッド)。
IsDescendant 渡したノードがこの hierarchyid 型ノードの子孫である場合、true を返します。
Parse 階層の文字列表現を hierarchyid 型の値に変換します (静的メソッド)。
Reparent 階層内のノードを同じ階層内の新しい場所に移動します。
ToString hierarchyid 型ノードの論理表現が含まれた文字列を返します。

空間データ型

空間データとは、主に地球上の地理的な場所や地形を表すデータです。このデータの例としては、目印となる建物、道路、会社の場所などが考えられます。SQL Server 2008 では、このようなデータを操作するための地理データ型とジオメトリ データ型が提供されます。

地理データ型は、3 次元の情報を操作します。この 3 次元モデルは、湾曲した地球の表面を考慮して計算を行います。位置に関する情報は、緯度と経度で提供されます。このモデルは、海外輸送、軍事計画、近距離通信など、地球の表面に基づいた計算を行うアプリケーションに適しています。データを緯度と経度で格納する場合は、このモデルを使用します。

ジオメトリ データ型は、2 次元モデルを操作します。このモデルでは、地球を特定のポイントを基点とする平面として扱います。この平面モデルは、地球の湾曲を考慮しないので、建物の内部の地図を作成するデータベース アプリケーションなど、主に短い距離を表す場合に使用されます。

地理型とジオメトリ型は、Well-Known Text (WKT) または Well-Known Binary (WKB) 形式で指定されたベクタ オブジェクトから構築されます。これらの形式は、Open Geospatial Consortium (OGC) Simple Features for SQL Specification で規定されている空間データの転送形式です。図 10 は、SQL Server 2008 でサポートされている 7 種類のベクタ オブジェクトを示しています。

Figure 10 Vector objects supported by SQL Server 2008

オブジェクト 説明
Point 1 つの場所です。
MultiPoint 複数の場所のコレクションです。
LineString 線でつながれた 0 個以上のポイントです。
MultiLineString 複数の LineString のコレクションです。
Polygon 一連の LineString で囲まれる隣接領域です。
MultiPolygon 複数の多角形のコレクションです。
GeometryCollection ジオメトリ型のコレクションです。

1 つまたは複数のベクタ オブジェクトを使用して地理型を構築するには、まず T-SQL スクリプト内で地理型を宣言します (図 11 参照)。次に、図 12 の一覧に記載されているいずれかのメソッドを呼び出し、ベクタ オブジェクトと Spatial Reference ID (SRID) を示す文字列を渡します。SRID は、European Petroleum Survey Group によって定義された空間参照 ID システムであり、地図作成、測量、および測地に関する一連の標準の一部として策定されました。各 SRID は、地理に関する計算で使用される楕円の種類を特定します。地球は完全な球体ではないので、このような処理が必要になります。SQL Server 2008 は、同じ SRID に対してのみ計算を実行できます。

Figure 12 Construct objects for geography and geometry

メソッド 説明
STGeomFromText 入力テキストから任意の種類の地理インスタンスを構築します。
STPointFromText 入力テキストから Point 型の地理インスタンスを構築します。
STMPointFromText 入力テキストから MultiPoint 型の地理インスタンスを構築します。
STLineFromText 入力テキストから LineString 型の地理インスタンスを構築します。
STMLineFromText 入力テキストから MultiLineString 型の地理インスタンスを構築します。
STPolyFromText 入力テキストから Polygon 型の地理インスタンスを構築します。
STMPolyFromText 入力テキストから MultiPolygon 型の地理インスタンスを構築します。
STGeomCollFromText 入力テキストから GeometryCollection 型の地理インスタンスを構築します。

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

地理型とジオメトリ型の違い

地理データ型とジオメトリ データ型はそれぞれ異なる種類のデータを操作することを目的としており、注意すべき重要な違いがいくつかあります。ジオメトリ データ型では、距離と領域がインスタンスの座標と同じ測定単位で提供されます。たとえば、ポイント (0,0) から (6,8) までの距離は常に 10 です。緯度と経度で表現される楕円の座標と連動する地理型の場合、この動作は異なります。

緯度と経度の組み合わせで座標を表現した場合、GEOMETRY データ型は一貫性のない結果を返します。次の T-SQL コードは、ポイント (90 0) と (90 180) の間の距離を計算しています。どちらのポイントも北極を参照しているので、両者間の距離は 0 になる必要があります。ただし GEOMETRY の場合、算出される距離は 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

また、これら 2 つのデータ型では、空間データの方向も異なります。ジオメトリ データ型によって使用される 2 次元システムでは、多角形の向きは重要な要素ではありません。たとえば、座標 (0, 0)、(10, 0)、(0, 20)、(0, 0) から構成される多角形は、(0, 0)、(0, 20)、(10, 0)、(0, 0) から構成される多角形と同じものであると見なされます。ただし、地理データ型によって使用されるデータ モデルでは、向きを指定しなければ多角形の特性が不明確になります。たとえば、赤道を囲むリングについて考えてみましょう。このリングによって表された多角形は、北半球と南半球のどちらを参照するのでしょうか。地理データを操作する場合は、その向きと場所を正確に記述する必要があるということを覚えておいてください。

また、SQL Server 2008 の地理データ型には、いくつかの制限があります。たとえば、各地理インスタンスは、1 つの半球内に収まる必要があります。空間オブジェクトのサイズが大きすぎる場合は例外が発生し、ArgumentException がスローされます。地理データ型は 2 つの入力値を処理し、メソッドの結果が 1 つの半球内に収まらない場合は NULL を返します。

SQL Server では、地理インスタンスとジオメトリ インスタンスを操作できる数多くのメソッドが提供されます。図 13 は、SQL Server 2008 で提供されるメソッドを使用して空間データを操作する例を示しています。スペースの関係上、ここでは詳しく説明できないので、詳細については SQL Server オンライン ブックを参照してください。

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

今回ご紹介した、SQL Server 2008 で新しく提供される 7 つのデータ型に関する情報が皆さんのお役に立てば幸いです。

Kelly Wilson は、20 年以上にわたってソフトウェア エンジニアリングに携わってきました。今までに開発を担当したのは、SQL Server、3D グラフィックス、ゲーム、および色彩科学に関するアプリケーションです。現在は、マイクロソフトの SQL Server グループでプログラミング ライターとして勤務しています。

© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; 許可なしに一部または全体を複製することは禁止されています.