Как вставить точки из подзапроса как объект SDO_GEOMETRY в пространственную базу данных Oracle?
Скажем, у меня есть таблица с именем buildings
который может быть создан с помощью следующего запроса:
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
, Следующие две точки вставляются непосредственно в вышеупомянутый запрос:
- 24,916312, 91,832393
- 24,916392, 91,832678
Теперь я хочу вставить эти две точки из двух разных подзапросов.
Подзапросы будут выглядеть следующим образом:
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
Я прогуглил это и исследовал несколько блогов, но безуспешно.
NB:
Название казалось неуместным, но прямые версии подзапросов возвращают объект SDO_GEOMETRY
, Если вы изучали пространственные запросы оракула, то вам ясно, что я просто извлекаю значения X и Y из возвращенного объекта.
2 ответа
Я нашел способ вставить. Может существовать эффективный способ, но этот работает нормально.
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
)
);
Функция SDO_CENTROID() возвращает объект SDO_GEOMETRY, который затем можно использовать для вставки в таблицу результатов.
Предполагая, что это ваша таблица результатов
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+ х, 180-й). Это бессмысленно.
Во всяком случае, вы говорите, что выше не то, что вы хотите. Я продолжу гадать и предположить, что вы хотите построить прямоугольник, в котором два угла вычисляются как центроиды в двух ваших зданиях. Для этого нужно немного 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;
Если это не то, что вы ожидаете, то, пожалуйста, перефразируйте вопрос (а также уточните реальную бизнес-проблему, которую вы пытаетесь решить)