如何在 Oracle 空间数据库中插入来自 sub-query 的点作为 SDO_GEOMETRY 的 object?

How to insert points coming from sub-query as an object of SDO_GEOMETRY in Oracle spatial database?

说,我有一个名为 buildings 的 table,可以通过以下查询创建:

create table buildings(
  building_id number primary key,
  building_name varchar2(32),
  shape sdo_geometry
);

我可以通过以下查询向其中插入一个矩形:

insert into buildings values(
  4, -- index
  'Reading Room', -- building_name
  sdo_geometry(
    2003, --SDO_GTYPE: dltt - 2(2D)0(linear referencing)03(polygon)
    8307, --SDO_SRID: coordinate system
    null, --SDO_POINT: it is for point inserting, if the next two field = null, then it could not be null.
    sdo_elem_info_array( --SDO_ELEM_INFO:
    1, --SDO_STARTING_OFFSET: indicates from which index of the next param of SDO_GEOMETRY would be considered, starts from 1.
    1003, --SDO_ETYPE: 1(exterior, interior  - 2)003(this digits usually comes from SDO_GTYPE)
    3),  --SDO_INTERPRETATION: 1 - simple polygon, 2 - polygon connecting arcs, 3 - rectangle, 4 - circle etc.
    sdo_ordinate_array(
      24.916312, 91.832393,
      24.916392, 91.832678
    ) --SDO_ORDINATES: co-ordinates of the geometry
                              -- two corner points of the main diagonal
  )
);

这里,两个大地测量点来自真实数据,作为 sdo_ordinate_array 的 object。在上面的查询中直接插入了以下两点:

  1. 24.916312, 91.832393
  2. 24.916392, 91.832678

现在,我想插入来自两个不同 sub-query 的这两点。

Sub-queries 会像下面这样:

SELECT 180+SDO_GEOM.SDO_CENTROID(c.shape, m.diminfo).SDO_POINT.X, 
  180-SDO_GEOM.SDO_CENTROID(c.shape, m.diminfo).SDO_POINT.Y
  FROM buildings c, user_sdo_geom_metadata m 
  WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
  AND c.building_name = 'IICT';

因此,查询结果如下:

         X          Y
---------- ----------
24.9181097 91.83097409 

如何将此结果转换为逗号分隔值,例如:24.9181097, 91.83097409?

这样我就可以替换下面的代码:

sdo_ordinate_array(
    24.916312, 91.832393,
    24.916392, 91.832678
) --SDO_ORDINATES: co-ordinates of the geometry

与:

sdo_ordinate_array(
    (/*sub-query*/),
    (/*another-subquery*/)
) --SDO_ORDINATES: co-ordinates of the geometry

我有 google 它并浏览了几个博客,但没有运气。

N.B.:

标题似乎不合适,但是 sub-queries return SDO_GEOMETRY 的 object 的直接版本。如果您探索过 oracle 空间查询,那么您很清楚我只是从 returned object.

中检索 X 和 Y 的值

SDO_CENTROID() 函数 returns 一个 SDO_GEOMETRY 对象,然后您可以将其用于插入结果 table.

假设这是你的结果table

create table building_centroids (
  building_id number primary key,
  centroid sdo_geometry
);

然后下面将用你所有建筑物的质心填充它

insert into building_centroids (building_id, centroid)
select building_id, sdo_geom.sdo_centroid(shape, 0.05)
from buildings;

我不明白你为什么要改变坐标(180+x,180-y)。这毫无意义。

反正你说上面的不是你想要的。我将继续猜测并假设您想构建一个矩形,其中两个角被计算为您的两个建筑物的质心。这需要一点 PL/SQL,像这样:

首先定义一个从两个输入点构建矩形的函数

create or replace function rectangle_from_points (
  point_1 sdo_geometry,
  point_2 sdo_geometry
) 
return sdo_geometry
as 
  rectangle sdo_geometry;
begin
  -- Initialize resulting rectangle
  rectangle := sdo_geometry (2003, point_1.sdo_srid, null,
     sdo_elem_info_array (1,1003,3),
     sdo_ordinate_array()
  );
  -- Fill it with the two point points
  rectangle.sdo_ordinates.extend(4);
  rectangle.sdo_ordinates(1) := point_1.sdo_point.x;
  rectangle.sdo_ordinates(2) := point_1.sdo_point.y;
  rectangle.sdo_ordinates(3) := point_2.sdo_point.x;
  rectangle.sdo_ordinates(4) := point_2.sdo_point.y;
  -- Return it
  return rectangle;
end;
/

现在,像这样使用它:

select rectangle_from_points (
  (
    select sdo_geom.sdo_centroid(shape, 0.05)
    from buildings
    building_id = 42
  ),
  (
    select sdo_geom.sdo_centroid(shape, 0.05)
    from buildings
    building_id = 564
  )
)
from dual;

如果这不是您所期望的,那么请重新表述问题(并阐明您要解决的实际业务问题)

我找到了插入的方法。可能存在有效的方法,但这个方法很好用。

sdo_ordinate_array(

    --this sub-query returns the Longitude of the first point
    (SELECT SDO_GEOM.SDO_CENTROID(c.shape, m.diminfo).SDO_POINT.X X
    FROM buildings c, user_sdo_geom_metadata m 
    WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
    AND c.building_name = 'IICT'), 

    --this sub-query returns the Latitude of the first point
    (SELECT SDO_GEOM.SDO_CENTROID(c.shape, m.diminfo).SDO_POINT.Y Y
    FROM buildings c, user_sdo_geom_metadata m 
    WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
    AND c.building_name = 'IICT'), 

    --this sub-query returns the Longitude of the second point
    (SELECT SDO_GEOM.SDO_POINTONSURFACE(c.shape, m.diminfo).SDO_POINT.X X 
    FROM buildings c, user_sdo_geom_metadata m 
    WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
    AND c.building_name = 'IICT'), 

    --this sub-query returns the Latitude of the second point
    (SELECT SDO_GEOM.SDO_POINTONSURFACE(c.shape, m.diminfo).SDO_POINT.Y Y 
    FROM buildings c, user_sdo_geom_metadata m 
    WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
    AND c.building_name = 'IICT') 

) --SDO_ORDINATES: co-ordinates of the geomentry

sdo_ordinate_array只拿分,不拿sdo_geometry的对象。所以,我必须分别获取经度和纬度。

因此,完整的插入查询如下所示:

insert into buildings values(
  4, -- index
  'Reading Room', -- building_name
   sdo_geometry(
    2003, --SDO_GTYPE: dltt - 2(2D)0(linear referencing)03(polygon)
    8307, --SDO_SRID: coordinate system
    null, --SDO_POINT: it is for point inserting, if the next two field = null, then it could not be null.
    sdo_elem_info_array( --SDO_ELEM_INFO:
    1, --SDO_STARTING_OFFSET: indicates from which index of the next param of SDO_GEOMETRY would be considered, starts from 1.
    1003, --SDO_ETYPE: 1(exterior, interior  - 2)003(this digits usually comes from SDO_GTYPE)
    3),  --SDO_INTERPRETATION: 1 - simple polygon, 2 - polygon connecting arcs, 3 - rectangle, 4 - circle etc.

    sdo_ordinate_array(

        --this sub-query returns the Longitude of the first point
        (SELECT SDO_GEOM.SDO_CENTROID(c.shape, m.diminfo).SDO_POINT.X X
        FROM buildings c, user_sdo_geom_metadata m 
        WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
        AND c.building_name = 'IICT'), 

        --this sub-query returns the Latitude of the first point
        (SELECT SDO_GEOM.SDO_CENTROID(c.shape, m.diminfo).SDO_POINT.Y Y
        FROM buildings c, user_sdo_geom_metadata m 
        WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
        AND c.building_name = 'IICT'), 

        --this sub-query returns the Longitude of the second point
        (SELECT SDO_GEOM.SDO_POINTONSURFACE(c.shape, m.diminfo).SDO_POINT.X X 
        FROM buildings c, user_sdo_geom_metadata m 
        WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
        AND c.building_name = 'IICT'), 

        --this sub-query returns the Latitude of the second point
        (SELECT SDO_GEOM.SDO_POINTONSURFACE(c.shape, m.diminfo).SDO_POINT.Y Y 
        FROM buildings c, user_sdo_geom_metadata m 
        WHERE m.table_name = 'BUILDINGS' AND m.column_name = 'SHAPE' 
        AND c.building_name = 'IICT') 

    ) --SDO_ORDINATES: co-ordinates of the geomentry
 )
);