この章では、『ISO 13249-3, Information technology - Database languages - SQL Multimedia and Application Packages - Part 3: Spatial』で指定されたST_xxx型の使用に対する、Oracle Spatialでのサポートについて説明します。この章の内容は次のとおりです。
SQL MultimediaのST_GEOMETRYルート・タイプ(サブタイプを含む)とOracle SpatialのSDO_GEOMETRY型(2.2項を参照)は、基本的に相互運用できます。ST_GEOMETRYサブタイプは次のとおりです。
ST_CIRCULARSTRING
ST_COMPOUNDCURVE
ST_CURVE
ST_CURVEPOLYGON
ST_GEOMCOLLECTION
ST_LINESTRING
ST_MULTICURVE
ST_MULTILINESTRING
ST_MULTIPOINT
ST_MULTIPOLYGON
ST_MULTISURFACE
ST_POINT
ST_POLYGON
ST_SURFACE
ST_GEOMETRY型には、SDO_GEOMETRYオブジェクトを使用してその型のインスタンスを作成するための追加コンストラクタ・メソッド(つまり、ISO標準で定義されたコンストラクタに加え)があります。このコンストラクタには、次の形式があります。
ST_GEOMETRY(geom SDO_GEOMETRY);
例3-1では、SDO_GEOMETRY型のかわりに空間列にST_GEOMETRY型を使用して表を作成し、ST_GEOMETRYコンストラクタを使用して、その表に行を挿入する際のSHAPE列の値を指定します。
例3-1 空間列でのST_GEOMETRY型の使用
CREATE TABLE cola_markets ( mkt_id NUMBER PRIMARY KEY, name VARCHAR2(32), shape ST_GEOMETRY); INSERT INTO cola_markets VALUES( 1, 'cola_a', ST_GEOMETRY( SDO_GEOMETRY( 2003, -- two-dimensional polygon NULL, NULL, SDO_ELEM_INFO_ARRAY(1,1003,3), -- one rectangle (1003 = exterior) SDO_ORDINATE_ARRAY(1,1, 5,7) -- only 2 points needed to -- define rectangle (lower left and upper right) with -- Cartesian-coordinate data ) ) );
ST_GEOMETRY型の空間列を持つ表を作成する場合は、SDO_GEOMETRY型を使用して定義される空間データの場合と同様に、その情報をUSER_SDO_GEOM_METADATAビューに追加し、ST_GEOMETRY列に空間索引を作成する必要があります。これらの操作を実行した後に、ST_GEOMETRYデータでOracle Spatialの演算子(第19章を参照)を使用できます。標準で定義されている演算子の他に、SDO_NN演算子およびSDO_WITHIN_DISTANCE演算子も使用できます。
例3-2では、2.1項の例2-1と基本的に同じ操作を実行しますが、空間列に対して、SDO_GEOMETRY型のかわりにST_GEOMETRY型を使用します。
例3-2 ST_GEOMETRYデータの作成、索引付け、格納および問合せ
CREATE TABLE cola_markets (
mkt_id NUMBER PRIMARY KEY,
name VARCHAR2(32),
shape ST_GEOMETRY);
INSERT INTO cola_markets VALUES(
1,
'cola_a',
ST_GEOMETRY(
SDO_GEOMETRY(
2003, -- two-dimensional polygon
NULL,
NULL,
SDO_ELEM_INFO_ARRAY(1,1003,3), -- one rectangle (1003 = exterior)
SDO_ORDINATE_ARRAY(1,1, 5,7) -- only 2 points needed to
-- define rectangle (lower left and upper right) with
-- Cartesian-coordinate data
)
)
);
INSERT INTO cola_markets VALUES(
2,
'cola_b',
ST_GEOMETRY(
SDO_GEOMETRY(
2003, -- two-dimensional polygon
NULL,
NULL,
SDO_ELEM_INFO_ARRAY(1,1003,1), -- one polygon (exterior polygon ring)
SDO_ORDINATE_ARRAY(5,1, 8,1, 8,6, 5,7, 5,1)
)
)
);
INSERT INTO cola_markets VALUES(
3,
'cola_c',
ST_GEOMETRY(
SDO_GEOMETRY(
2003, -- two-dimensional polygon
NULL,
NULL,
SDO_ELEM_INFO_ARRAY(1,1003,1), -- one polygon (exterior polygon ring)
SDO_ORDINATE_ARRAY(3,3, 6,3, 6,5, 4,5, 3,3)
)
)
);
INSERT INTO cola_markets VALUES(
4,
'cola_d',
ST_GEOMETRY(
SDO_GEOMETRY(
2003, -- two-dimensional polygon
NULL,
NULL,
SDO_ELEM_INFO_ARRAY(1,1003,4), -- one circle
SDO_ORDINATE_ARRAY(8,7, 10,9, 8,11)
)
)
);
---------------------------------------------------------------------------
-- UPDATE METADATA VIEW --
---------------------------------------------------------------------------
-- Update the USER_SDO_GEOM_METADATA view. This is required before
-- the spatial index can be created. Do this only once for each layer
-- (that is, table-column combination; here: cola_markets and shape).
INSERT INTO user_sdo_geom_metadata
(TABLE_NAME,
COLUMN_NAME,
DIMINFO,
SRID)
VALUES (
'cola_markets',
'shape',
SDO_DIM_ARRAY( -- 20X20 grid
SDO_DIM_ELEMENT('X', 0, 20, 0.005),
SDO_DIM_ELEMENT('Y', 0, 20, 0.005)
),
NULL -- SRID
);
-------------------------------------------------------------------
-- CREATE THE SPATIAL INDEX --
-------------------------------------------------------------------
CREATE INDEX cola_spatial_idx
ON cola_markets(shape)
INDEXTYPE IS MDSYS.SPATIAL_INDEX;
---------------------------
-- SDO_NN and SDO_WITHIN_DISTANCE
--------------------------
-- SDO_NN operator.
SELECT /*+ INDEX(c cola_spatial_idx) */ c.mkt_id, c.name
FROM cola_markets c
WHERE SDO_NN(c.shape, sdo_geometry(2001, NULL,
sdo_point_type(10,7,NULL), NULL, NULL), 'sdo_num_res=2') = 'TRUE';
-- SDO_NN_DISTANCE ancillary operator
SELECT /*+ INDEX(c cola_spatial_idx) */
c.mkt_id, c.name, SDO_NN_DISTANCE(1) dist
FROM cola_markets c
WHERE SDO_NN(c.shape, sdo_geometry(2001, NULL,
sdo_point_type(10,7,NULL), NULL, NULL),
'sdo_num_res=2', 1) = 'TRUE' ORDER BY dist;
-- SDO_WITHIN_DISTANCE operator (two examples)
SELECT c.name FROM cola_markets c WHERE SDO_WITHIN_DISTANCE(c.shape,
SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1,1003,3),
SDO_ORDINATE_ARRAY(4,6, 8,8)),
'distance=10') = 'TRUE';
-- What geometries are within a distance of 10 from a query window
-- (here, a rectangle with lower-left, upper-right coordinates 4,6, 8,8)?
-- But exclude geoms with MBRs with both sides < 4.1, i.e., cola_c and cola_d.
SELECT c.name FROM cola_markets c WHERE SDO_WITHIN_DISTANCE(c.shape,
SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1,1003,3),
SDO_ORDINATE_ARRAY(4,6, 8,8)),
'distance=10 min_resolution=4.1') = 'TRUE';
-------------------------------------
-- Some ST_GEOMETRY member functions
-------------------------------------
SELECT c.shape.GET_WKB()
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.GET_WKT()
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_COORDDIM()
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_ISVALID()
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_SRID()
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_SRID(8307)
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_ISEMPTY()
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_ENVELOPE()
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_BOUNDARY()
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_GEOMETRYTYPE()
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_ISSIMPLE()
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_DIMENSION()
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_CONVEXHULL()
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_CENTROID()
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_GETTOLERANCE()
FROM cola_markets c WHERE c.name = 'cola_b';
-- Some member functions that require a parameter
DECLARE
cola_a_geom ST_GEOMETRY;
cola_b_geom ST_GEOMETRY;
cola_c_geom ST_GEOMETRY;
cola_d_geom ST_GEOMETRY;
returned_geom ST_GEOMETRY;
returned_number NUMBER;
BEGIN
-- Populate geometry variables with cola market shapes.
SELECT c.shape INTO cola_a_geom FROM cola_markets c
WHERE c.name = 'cola_a';
SELECT c.shape INTO cola_b_geom FROM cola_markets c
WHERE c.name = 'cola_b';
SELECT c.shape INTO cola_c_geom FROM cola_markets c
WHERE c.name = 'cola_c';
SELECT c.shape INTO cola_d_geom FROM cola_markets c
WHERE c.name = 'cola_d';
SELECT c.shape.ST_EQUALS(cola_a_geom) INTO returned_number
FROM cola_markets c WHERE c.name = 'cola_b';
DBMS_OUTPUT.PUT_LINE('Is cola_b equal to cola_a?: ' ││ returned_number);
SELECT c.shape.ST_SYMMETRICDIFFERENCE(cola_a_geom) INTO returned_geom
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_DISTANCE(cola_d_geom) INTO returned_number
FROM cola_markets c WHERE c.name = 'cola_b';
DBMS_OUTPUT.PUT_LINE('Distance between cola_b equal to cola_d: ' ││ returned_number);
SELECT c.shape.ST_INTERSECTS(cola_a_geom) INTO returned_number
FROM cola_markets c WHERE c.name = 'cola_b';
DBMS_OUTPUT.PUT_LINE('Does cola_b intersect cola_a?: ' ││ returned_number);
SELECT c.shape.ST_CROSS(cola_a_geom) INTO returned_number
FROM cola_markets c WHERE c.name = 'cola_b';
DBMS_OUTPUT.PUT_LINE('Does cola_b cross cola_a?: ' ││ returned_number);
SELECT c.shape.ST_DISJOINT(cola_a_geom) INTO returned_number
FROM cola_markets c WHERE c.name = 'cola_b';
DBMS_OUTPUT.PUT_LINE('Is cola_b disjoint with cola_a?: ' ││ returned_number);
SELECT c.shape.ST_TOUCH(cola_a_geom) INTO returned_number
FROM cola_markets c WHERE c.name = 'cola_b';
DBMS_OUTPUT.PUT_LINE('Does cola_b touch cola_a?: ' ││ returned_number);
SELECT c.shape.ST_WITHIN(cola_a_geom) INTO returned_number
FROM cola_markets c WHERE c.name = 'cola_b';
DBMS_OUTPUT.PUT_LINE('Is cola_b within cola_a?: ' ││ returned_number);
SELECT c.shape.ST_OVERLAP(cola_a_geom) INTO returned_number
FROM cola_markets c WHERE c.name = 'cola_b';
DBMS_OUTPUT.PUT_LINE('Does cola_b overlap cola_a?: ' ││ returned_number);
SELECT c.shape.ST_CONTAINS(cola_a_geom) INTO returned_number
FROM cola_markets c WHERE c.name = 'cola_b';
DBMS_OUTPUT.PUT_LINE('Does cola_b contain cola_a?: ' ││ returned_number);
SELECT c.shape.ST_INTERSECTION(cola_a_geom) INTO returned_geom
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_DIFFERENCE(cola_a_geom) INTO returned_geom
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_UNION(cola_a_geom) INTO returned_geom
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_SYMDIFFERENCE(cola_a_geom) INTO returned_geom
FROM cola_markets c WHERE c.name = 'cola_b';
SELECT c.shape.ST_TOUCHES(cola_a_geom) INTO returned_number
FROM cola_markets c WHERE c.name = 'cola_b';
DBMS_OUTPUT.PUT_LINE('Does cola_b touch cola_a?: ' ││ returned_number);
SELECT c.shape.ST_CROSSES(cola_a_geom) INTO returned_number
FROM cola_markets c WHERE c.name = 'cola_b';
DBMS_OUTPUT.PUT_LINE('Does cola_b cross cola_a?: ' ││ returned_number);
END;
/
SQL Multimedia規格では、ST_ xxxで使用する許容差が定義されていないため、Spatialでは、ST_GEOMETRY型のすべてのメンバー・メソッドにデフォルト値の0.005が使用されます。ST_GEOMETRYメンバー・ファンクションで使用する許容差に異なる値を指定する場合は、SDO_ST_TOLERANCE表に指定する値を挿入してデフォルトを上書きする必要があります。
SDO_ST_TOLERANCE表はグローバルな一時表であり、ST_GEOMETRYメンバー・メソッドで使用される許容差を指定する1行があります。この表には、(tolerance NUMBER)で定義される1列があります。
空間索引を使用するSpatialのすべての演算子に対し、Spatialでは、USER_SDO_GEOM_METADATAビューの空間列に指定された許容差が使用されます。
一部のサード・パーティ・ベンダーでは、OracleでST_xxx型の独自のバージョンをサポートしています。たとえば、ベンダーがST_GEOMETRY型の独自のバージョンを作成する場合もあります。
サード・パーティの名前とOracle提供の名前が競合することを回避するには、サード・パーティのST_xxx型をOracleに実装する際に、スキーマの接頭辞を使用する必要があります。たとえば、列の型に単にST_GEOMETRYを指定すると、OracleにST_GEOMETRY型を実装する際にその列が作成されることになります。
Oracle Spatialでは、『OpenGIS Implementation Specification for Geographic information - Simple feature access - Part 1: Common architecture』で指定された注釈テキストをサポートしています。この仕様では、注釈テキストは、地理関連データまたはアドホック・データ、およびプロセス関連情報を表示可能なテキストとして含む、単純に挿入されたテキストとして定義されています。このテキストは、エディタまたは単純な地図で表示するために使用できます。通常、完全な地図製作における品質としては不十分ですが、あらゆるアプリケーションで必要となるテキスト機能をほぼ果たすことができます。
ST_ANNOTATION_TEXTオブジェクト型は、注釈テキストの格納に使用できます。 この型には、注釈テキストを表に挿入するコンストラクタがあります(3.4.1項を参照)。
USER_ANNOTATION_TEXT_METADATAビューおよびALL_ANNOTATION_TEXT_METADATAビューは、注釈テキストに関連するメタデータを格納します(3.4.2項を参照)。
注釈テキストのオブジェクトには、オブジェクトの配列が含まれます。ここでは、各オブジェクトは、テキスト・ラベル、テキスト・ラベルのレンダリングを開始する点、引き出し線(通常、テキスト・ラベルから地図上の関連付けられた点)、およびオプションで追加の属性情報で構成されます。通常、単一の注釈テキストのオブジェクトには、地図のすべてのテキスト・ラベルを含めることができます。
各テキスト・ラベルのオブジェクトは、次のように定義されています。
Name Null? Type ----------------------------------------- -------- ---------------------------- PRIVATEVALUE VARCHAR2(4000) PRIVATELOCATION MDSYS.SDO_GEOMETRY PRIVATELEADERLINE MDSYS.SDO_GEOMETRY PRIVATETEXTATTRIBUTES VARCHAR2(4000)
単一の点に注釈を挿入する場合は、ST_ANNOTATION_TEXTコンストラクタを使用します。このコンストラクタは、例3-3に示すように、配列を使用して単一の点に情報を指定します。この例では、ST_ANNOTATION_TEXT型の列を含む表を作成し、INSERT文でST_ANNOTATION_TEXTコンストラクタを使用して、1つの行を挿入します。
例3-3 ST_ANNOTATION_TEXTコンストラクタの使用
CREATE TABLE my_annotations (id NUMBER, textobj ST_ANNOTATION_TEXT);
INSERT INTO my_annotations VALUES (2,
ST_ANNOTATION_TEXT(
ST_ANNOTATIONTEXTELEMENT_ARRAY(
ST_ANNOT_TEXTELEMENT_ARRAY(
ST_ANNOTATIONTEXTELEMENT(
'Sample Label 2',
SDO_GEOMETRY(2001,null,sdo_point_type(10,10,null),null,null),
SDO_GEOMETRY(2002,null,null,
SDO_ELEM_INFO_ARRAY(1,2,1),
SDO_ORDINATE_ARRAY(5,10, 10,10)),
NULL)))));
例3-3のST_ANNOTATION_TEXTコンストラクタでは、ST_ANNOTATIONTEXTELEMENTサブ要素で、次のような属性を指定しています。
注釈テキストのメタデータは、MDSYSが所有するグローバル表に格納されます。ユーザーは、このグローバル表を直接更新しないでください。Spatialのユーザーは、ユーザーに関連付けられたスキーマで使用可能な次のビューを持っています。
USER_ANNOTATION_TEXT_METADATAには、ユーザー(スキーマ)が所有する表のすべての注釈テキストについてのメタデータ情報が含まれます。このビューのみが更新可能であり、Spatialのユーザーは、空間表に関連するメタデータをこのビューに挿入する必要があります。
ALL_ANNOTATION_TEXT_METADATAには、ユーザーがSELECT権限を持つ、表のすべての注釈テキストのメタデータ情報が含まれます。
これらのビューの移入は、Spatialのユーザーの責任において行います。注釈テキストの各オブジェクトについて、USER_ANNOTATION_TEXT_METADATAビューに適切な行を挿入する必要があります。Oracle Spatialでは、ALL_ANNOTATION_TEXT_METADATAビューも更新され、USER_ANNOTATION_TEXT_METADATAに挿入した行が確実に反映されます。
USER_ANNOTATION_TEXT_METADATAビューとALL_ANNOTATION_TEXT_METADATAビューのどちらにも表3-1に示す列が含まれますが、USER_ANNOTATION_TEXT_METADATAビューにはOWNER列は含まれません。列をビュー定義の順に示します。
表3-1 注釈テキストのメタデータ・ビューの列
| 列名 | データ型 | 説明 |
|---|---|---|
|
OWNER |
VARCHAR2(32) |
TABLE_NAME列で指定された表の所有者(ALL_ANNOTATION_TEXT_METADATAビューのみ)。 |
|
TABLE_NAME |
VARCHAR2(32) |
ST_ANNOTATION_TEXT型の列を含む表の名前。 |
|
COLUMN_NAME |
VARCHAR2(1024) |
ST_ANNOTATION_TEXT型の列の名前。 |
|
TEXT_EXPRESSION |
VARCHAR2(4000) |
ラベルにテキストが指定されていない場合に使用できる値。OpenGISの仕様によると、挿入するテキストは、VALUEがNULLでない場合、最初に現行の要素のVALUEの内容から取得されます。それ以外の場合、テキストは最初のNULL以外の先行する要素のVALUEから取得されます。すべての先行する要素がNULLのVALUEフィールドの場合、VALUEはメタデータ表のTEXT_EXPRESSIONから取得されます。 |
|
TEXT_ATTRIBUTES |
VARCHAR2(4000) |
ラベル・テキストのスタイルおよびレイアウトについて、デフォルトのテキスト表示属性(フォント・ファミリーおよびフォント・サイズ、水平スペースおよび垂直スペースなど)。ただし、ST_ANNOTATION_TEXTコンストラクタのPRIVATETEXTATTRIBUTES属性で上書きされた場合を除きます(3.4.1項を参照)。OpenGISの仕様の「XML for Text Attributes」の項で指定された形式を使用してください。 |