10.2 ファンクション索引のSDO_GEOMETRYオブジェクト

ファンクション空間索引を使用すると、ファンクションまたは式によって戻される(SDO_GEOMETRY型の)位置情報を使用した問合せが容易になります。この場合、空間索引は、ファンクションまたは式によって戻される事前計算値に基づいて作成されます。

ファンクション索引のメリット、オプション、要件の詳細および使用例については、次のマニュアルを参照してください。

ファンクション索引でのSDO_GEOMETRYオブジェクトの使用手順は次のとおりです。

  1. SDO_GEOMETRYオブジェクトを戻すファンクションを作成します。

    このファンクションは、DETERMINISTICとして宣言される必要があります。

  2. 空間データ表が存在しない場合は、空間データ表を作成し、その表にデータを挿入します。

  3. USER_SDO_GEOM_METADATAビューを更新します。

  4. 空間索引を作成します。

    ファンクション空間索引の場合、パラメータ数は32以下である必要があります。

  5. データに対して問合せを実行します。

この項の後半では、ファンクション索引の2つの使用例を示します。どちらの例でも、SDO_GEOMETRYオブジェクトを戻すファンクションを作成し、そのファンクションに対して空間索引を作成しています。最初の例では、ファンクションへの入力パラメータは、標準のOracleデータ型(NUMBER)です。2つ目の例では、ファンクションへの入力は、ユーザー定義のオブジェクト型です。

10.2.1 例: 標準型を使用したファンクション

次の例では、ファンクション索引に使用されるファンクションへの入力パラメータは、標準の数値(経度および緯度)です。

ある点の経度および緯度を戻すファンクションを作成し、そのファンクションを空間索引で使用するとします。まず、次の例に示すとおり、ファンクションを作成します。この例では、get_long_lat_ptというファンクションを作成します:

-- Create a function to return a point geometry (SDO_GTYPE = SDO_POINT2D) with
-- input of 2 numbers: longitude and latitude (SDO_SRID = 4326, for
-- "Longitude / Latitude (WGS 84)",  probably the most widely used 
--  coordinate system, and the one used for GPS devices.
-- Specify DETERMINISTIC for the function.

CREATE OR REPLACE FUNCTION get_long_lat_pt(longitude IN NUMBER, 
                                           latitude IN NUMBER)
RETURN SDO_GEOMETRY DETERMINISTIC IS
BEGIN
     IF (longitude IS NULL) OR (latitude IS NULL) THEN
         RETURN NULL;
     END IF;
     RETURN SDO_GEOMETRY(longitude, latitude);
END;
/

空間データ表が存在しない場合は、次の例に示すとおり、その表を作成し、それにデータを追加します。この例では、long_lat_tableという表を作成します:

CREATE TABLE long_lat_table 
(lon NUMBER, lat NUMBER, name VARCHAR2(32));

INSERT INTO long_lat_table VALUES (10,10, 'Place1');
INSERT INTO long_lat_table VALUES (20,20, 'Place2');
INSERT INTO long_lat_table VALUES (30,30, 'Place3');

ドット表記法を使用してスキーマ名およびファンクション名を指定し、USER_SDO_GEOM_METADATAビューを更新します。次の例では、SCOTT.GET_LONG_LAT_PT(LON,LAT)をこのメタデータ・ビューのCOLUMN_NAME (「COLUMN_NAME」を参照)として指定します。

-- Set up the metadata entry for this table.
-- The column name sets up the function on top
-- of the two columns used in this function,
-- along with the owner of the function.
INSERT INTO USER_SDO_GEOM_METADATA VALUES('LONG_LAT_TABLE',
 'scott.get_long_lat_pt(lon,lat)',
 SDO_DIM_ARRAY(
   SDO_DIM_ELEMENT('Longitude', -180, 180, 0.005),
   SDO_DIM_ELEMENT('Latitude', -90, 90, 0.005)), 4326);

パラメータでファンクション名を指定して、空間索引を作成します。たとえば:

CREATE INDEX long_lat_table_idx ON 
   long_lat_table(get_long_lat_pt(lon,lat))
   INDEXTYPE IS mdsys.spatial_index_v2;

データに対して問合せを実行します。次の例では、SDO_FILTER演算子へのコールで前述のユーザー定義ファンクションを指定します。

SELECT NAME FROM long_lat_table a
  WHERE SDO_FILTER(
    get_long_lat_pt(a.lon,a.lat), 
    SDO_GEOMETRY(10,10)
  )='TRUE';

NAME
--------------------------------
Place1

10.2.2 例: ユーザー定義のオブジェクト型を使用したファンクション

次の例では、ファンクション索引に使用されるファンクションへの入力パラメータは、経度および緯度を含むユーザー定義型のオブジェクトです。

ある点の経度および緯度を戻すファンクションを作成し、そのファンクションに対して空間索引を作成するとします。まず、次の例に示すとおり、ユーザー定義データ型を作成します。この例では、long_latというオブジェクト型、およびそのメンバー・ファンクションGetGeometry()を作成します:

CREATE TYPE long_lat as object ( 
   longitude NUMBER, 
   latitude NUMBER, 
MEMBER FUNCTION GetGeometry(SELF IN long_lat) 
RETURN SDO_GEOMETRY DETERMINISTIC) 
/ 

CREATE OR REPLACE TYPE BODY long_lat AS 
  MEMBER FUNCTION GetGeometry(SELF IN long_lat) 
  RETURN SDO_GEOMETRY IS 
    BEGIN 
       IF (longitude IS NULL) OR (latitude IS NULL) THEN
         RETURN NULL;
       END IF;
       RETURN SDO_GEOMETRY(longitude, latitude); 
    END; 
END; 
/ 
  

空間データ表が存在しない場合は、次の例に示すとおり、その表を作成し、それにデータを追加します。この例では、test_long_latという表を作成します:

CREATE TABLE test_long_lat 
   (location long_lat, name VARCHAR2(32)); 

INSERT INTO test_long_lat VALUES (long_lat(10,10), 'Place1'); 
INSERT INTO test_long_lat VALUES (long_lat(20,20), 'Place2'); 
INSERT INTO test_long_lat VALUES (long_lat(30,30), 'Place3'); 

ドット表記法を使用してスキーマ名、表名、ファンクション名およびパラメータ値を指定し、USER_SDO_GEOM_METADATAビューを更新します。次の例では、SCOTT.LONG_LAT.GETGEOMETRY(LOCATION)をこのメタデータ・ビュー内のCOLUMN_NAME (「COLUMN_NAME」を参照)として指定します。

INSERT INTO USER_SDO_GEOM_METADATA VALUES('test_long_lat', 
 'scott.long_lat.GetGeometry(location)', 
 SDO_DIM_ARRAY( 
   SDO_DIM_ELEMENT('Longitude', -180, 180, 0.005),
   SDO_DIM_ELEMENT('Latitude', -90, 90, 0.005)), 4326);

ドット表記法を使用して列名およびファンクション名を指定し、空間索引を作成します。たとえば:

CREATE INDEX test_long_lat_idx ON test_long_lat(location.GetGeometry()) 
  INDEXTYPE IS MDSYS.SPATIAL_INDEX_V2;

データに対して問合せを実行します。次の問合せでは、点(10,10)と空間的に相互作用するジオメトリの名前を要求する1次フィルタ処理を実行します。

SELECT a.name FROM test_long_lat a
  WHERE SDO_FILTER(a.location.GetGeometry(),
            SDO_GEOMETRY(10,10)
            ) = 'TRUE';