Oracle

將 SDO_GEOMETRY 線頂點提取到嵌套表列中(在查詢結果集中)

  • March 26, 2022

甲骨文 18c:

在相關文章中,我展示瞭如何使用**GetVertices()函式和Table()**函式來提取 SDO_GEOMETRY 線的頂點:

選擇 SDO_GEOMETRY 線頂點作為行

select  
   a.line_id, b.id as vertex_id, b.x, b.y
from
   a_sdo_geometry_tbl a, 
   table(sdo_util.getvertices(a.shape)) b       --<<--Here

  LINE_ID  VERTEX_ID          X          Y
---------- ---------- ---------- ----------
        1          1 671539.685 4863324.18
        1          2 671595.050 4863343.17
        1          3 671614.014 4863350.34
        1          4 671622.204 4863353.53

        2          1 71534.5567 4863119.99
        2          2 671640.738 4863157.13
        2          3 671684.862 4863172.02

作為學習練習,我想使用 PL/SQL創建自己的 GetVertices() 函式版本。

我對使用哪種機制持開放態度;以下任何一項都可以:

  • 基本 SQL
  • 模型子句
  • 自定義函式

關鍵是,我想學習如何提取頂點並將它們放入查詢中的嵌套表列中,就像 GetVertices() 函式一樣。

SDO_UTIL.GETVERTICES

此函式返回一個 MDSYS.VERTEX_SET_TYPE 對象,它由一個 MDSYS.VERTEX_TYPE 對象表組成。Oracle Spatial and Graph 將類型 VERTEX_SET_TYPE 定義為:

CREATE TYPE vertex_set_type as TABLE OF vertex_type;

Oracle Spatial and Graph 將對像類型 VERTEX_TYPE 定義為:

CREATE TYPE vertex_type AS OBJECT
   (x   NUMBER,
    y   NUMBER,
    z   NUMBER,
    w   NUMBER,
    v5  NUMBER,
    v6  NUMBER,
    v7  NUMBER,
    v8  NUMBER,
    v9  NUMBER,
    v10 NUMBER,
    v11 NUMBER,
    id  NUMBER);

注意:VERTEX_SET_TYPE 和 VERTEX_TYPE 類型僅供 Oracle 使用。不要在您創建的列定義或函式中使用這些類型。


問題:

有沒有辦法將 SDO_GEOMETRY 行的頂點提取到查詢中的嵌套表列中——而不使用 GetVertices() 函式?輸出將是查詢結果集,而不是靜態表。


提示:

以下功能可能有用:

PointN:返回一個點,它是頂點集合中的第 n 個頂點

GetNumVertices:返回輸入幾何中的頂點數。

似乎唯一的方法是創建自定義類型和自定義函式:

CREATE TYPE vertex_type_cust AS object
(
 x  NUMBER,
 y  NUMBER,
 z  NUMBER,
 w  NUMBER,
 id NUMBER );

CREATE TYPE vertex_set_type_cust AS TABLE OF vertex_type_cust;

CREATE OR replace FUNCTION getvertices_cust(geometry mdsys.sdo_geometry)
 RETURN vertex_set_type_cust
IS
 i      NUMBER;
 dims   NUMBER;
 coords NUMBER;
 result vertex_set_type_cust;
 dim mdsys.sdo_dim_array;
 is_zero BOOLEAN;
 etype   NUMBER;
BEGIN
 result := vertex_set_type_cust();
 -- handle the POINT case here
 IF (geometry.sdo_ordinates IS NULL) THEN
   result.extend;
   result(1) := vertex_type_cust(geometry.sdo_point.x, geometry.sdo_point.y, geometry.sdo_point.z,NULL,1);
   RETURN result;
 END IF;
 -- all other cases here
 coords := geometry.sdo_ordinates.count;
 dims := geometry.get_dims;
 IF (dims = 0) THEN
   RETURN result;
 END IF;
 coords := coords/dims;
 FOR i          IN 0 .. coords-1
 LOOP
   result.extend;
   IF (dims = 2) THEN
     result(i+1) := vertex_type_cust(geometry.sdo_ordinates(2*i+1), geometry.sdo_ordinates(2*i+2), NULL,NULL,i+1);
   ELSIF (dims = 3) THEN
     result(i+1) := vertex_type_cust(geometry.sdo_ordinates(3*i+1), geometry.sdo_ordinates(3*i+2), geometry.sdo_ordinates(3*i+3) ,NULL,i+1);
   ELSIF (dims = 4) THEN
     result(i+1) := vertex_type_cust(geometry.sdo_ordinates(4*i+1), geometry.sdo_ordinates(4*i+2), geometry.sdo_ordinates(4*i+3), geometry.sdo_ordinates(4*i+4), i+1);
   END IF;
 END LOOP;
 RETURN result;
END;

測試數據:

create table a_sdo_geometry_tbl (line_id integer, shape mdsys.sdo_geometry);

insert into a_sdo_geometry_tbl (line_id, shape) 
values (1, sdo_geometry (2002, null, null, sdo_elem_info_array (1,2,1), 
   sdo_ordinate_array (671539.6852734378,4863324.181436138, 671595.0500703361,4863343.166556185, 671614.013553706,4863350.343483042, 671622.2044153381,4863353.525396131))  );

insert into a_sdo_geometry_tbl (line_id, shape) 
values (2, sdo_geometry (2002, null, null, sdo_elem_info_array (1,2,1), 
   sdo_ordinate_array (71534.5567096211,4863119.991809748, 671640.7384688659,4863157.132745253, 671684.8621150404,4863172.022995591))  );

insert into a_sdo_geometry_tbl (line_id, shape) 
values (3, sdo_geometry (2002, null, null, sdo_elem_info_array (1,2,1), 
   sdo_ordinate_array (671622.2044153381,4863353.525396131, 671633.3267164109,4863357.846229106, 671904.0614077691,4863451.286166754))  );

insert into a_sdo_geometry_tbl (line_id, shape) 
values (4, sdo_geometry (2002, null, null, sdo_elem_info_array (1,2,1), 
   sdo_ordinate_array (671684.8620521119,4863172.022995591, 671892.1496144319,4863244.141440067, 671951.2156571196,4863264.824310392, 671957.4471461186,4863266.847617676, 671966.8243856924,4863269.146632658))  )

使用自定義函式:

select
   a.line_id,
   b.id as vertex_id,
   b.x, 
   b.y
from
   a_sdo_geometry_tbl a
cross join
   table(getvertices_cust(a.shape)) b  
order by 
   a.line_id, b.id;

引用自:https://dba.stackexchange.com/questions/299845