ファンクション空間索引を使用すると、ファンクションまたは式によって戻される(SDO_GEOMETRY型の)位置情報を使用した問合せが容易になります。この場合、空間索引は、ファンクションまたは式によって戻される事前計算値に基づいて作成されます。
ファンクション索引のメリット、オプション、要件の詳細および使用例については、次のマニュアルを参照してください。
『Oracle Database開発ガイド』
『Oracle Database管理者ガイド』
ファンクション索引でのSDO_GEOMETRYオブジェクトの使用手順は次のとおりです。
SDO_GEOMETRYオブジェクトを戻すファンクションを作成します。
このファンクションは、DETERMINISTICとして宣言される必要があります。
空間データ表が存在しない場合は、空間データ表を作成し、その表にデータを挿入します。
USER_SDO_GEOM_METADATAビューを更新します。
空間索引を作成します。
ファンクション空間索引の場合、パラメータ数は32以下である必要があります。
データに対して問合せを実行します。
この項の後半では、ファンクション索引の2つの使用例を示します。どちらの例でも、SDO_GEOMETRYオブジェクトを戻すファンクションを作成し、そのファンクションに対して空間索引を作成しています。最初の例では、ファンクションへの入力パラメータは、標準のOracleデータ型(NUMBER)です。2つ目の例では、ファンクションへの入力は、ユーザー定義のオブジェクト型です。
次の例では、ファンクション索引に使用されるファンクションへの入力パラメータは、標準の数値(経度および緯度)です。
ある点の経度および緯度を戻すファンクションを作成し、そのファンクションを空間索引で使用するとします。まず、次の例に示すとおり、ファンクションを作成します。この例では、GET_LONG_LAT_PTというファンクションを作成します。
-- Create a function to return a point geometry (SDO_GTYPE = 2001) with -- input of 2 numbers: longitude and latitude (SDO_SRID = 8307, 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 return sdo_geometry(2001, 8307, sdo_point_type(longitude, latitude, NULL),NULL, NULL); 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)), 8307);
パラメータでファンクション名を指定して、空間索引を作成します。次に例を示します。
create index LONG_LAT_TABLE_IDX on LONG_LAT_TABLE(get_long_lat_pt(lon,lat)) indextype is mdsys.spatial_index;
データに対して問合せを実行します。次の例では、SDO_FILTER演算子へのコールで前述のユーザー定義ファンクションを指定します。
select name from LONG_LAT_TABLE a where sdo_filter( get_long_lat_pt(a.lon,a.lat), sdo_geometry(2001, 8307, sdo_point_type(10,10,NULL), NULL, NULL) )='TRUE'; NAME -------------------------------- Place1
次の例では、ファンクション索引に使用されるファンクションへの入力パラメータは、経度および緯度を含むユーザー定義型のオブジェクトです。
ある点の経度および緯度を戻すファンクションを作成し、そのファンクションに対して空間索引を作成するとします。まず、次の例に示すとおり、ユーザー定義データ型を作成します。この例では、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 return sdo_geometry(2001, 8307, sdo_point_type(longitude, latitude, NULL), NULL,NULL); 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)), 8307);
ドット表記法を使用して列名およびファンクション名を指定し、空間索引を作成します。次に例を示します。
create index test_long_lat_idx on test_long_lat(location.GetGeometry()) indextype is mdsys.spatial_index;
データに対して問合せを実行します。次の問合せでは、点(10,10)と空間的に相互作用するジオメトリの名前を要求する1次フィルタ処理を実行します。
SELECT a.name FROM test_long_lat a WHERE SDO_FILTER(a.location.GetGeometry(), SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE(10,10,NULL), NULL, NULL) ) = 'TRUE';