Oracle空间问题:SDO_ORDINATE_ARRAY可以使用另一个Oracle表的查询结果填充吗?



我有一个业务开发目标,使用Oracle Spatial来存储坐标数据。目前,我们从正在海洋区域进行测量的科学家那里接收坐标,这些坐标以点的数字对或多边形的长varchar数组的形式存储在我们的Oracle数据库中。但是,我们希望通过使用Oracle Spatial来改进我们对这些数据的管理。

我们从科学家那里得到的坐标信息通常以CSV文件的形式出现,附带数据,并作为字段中的条目加载到Oracle表中。

我知道我可以手动将顶点输入到SDO_ORDINATE_ARRAY中,但是我们经常在一个CSV文件中提供数百个坐标对,这使得手动路由非常低效。

有人可以告诉我,如果有一种方法来填充的SDO_ORDINATE_ARRAY的内容,从数据库中已经存储的其他表拉出的信息?

下面是我尝试过的一个例子:

名为GEOMTEST的测试表组成的名字varchar2 (50)坐标varchar2 (4000)COORD_GEOM SDO_GEOMETRY

我在名字中填上了英国威尔士的卡迪根湾。COORDS是我在varchar2中存储为数组的多边形。这是从CSV文件导入的。COORD_GEOM就是我希望坐标的内容转移到。

我试图运行这段代码,但收到一个错误:

insert into geomtest (coord_geom) values(SDO_GEOMETRY(2003,4326,null,SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY values(select coordinates from geomtest));

我使用Toad作为客户机,错误是" error:第18行。第120列,第18行结束,第125列:Found 'values':保留字不能用作标识符。

我认为这与我在INSERT语句的SDO_ORDINATE_ARRAY部分中使用select语句有关,但我不确定如何继续。

我将感激任何意见,

多谢Sean

不幸的是,您不能直接将包含数字的字符串传递给SDO_ORDINATE_ARRAY构造函数。一种解决方案是编写一个自定义字符串标记器函数,该函数将坐标字符串解析为单个数字,并构建SDO_ORDINATE_ARRAY对象。这里有一个:

create or replace function tokenize (str clob)
return sdo_ordinate_array
is
s clob := str||',';
i number;
j number;
t sdo_ordinate_array := sdo_ordinate_array();
begin
i := 1;
loop
j := instr(s, ',', i);
exit when j = 0;
t.extend();
t(t.count) := to_number(substr(s,i,j-i));
i := j+1;
end loop;
return t;
end;
/
show errors

它是这样工作的。首先,让我们用几个示例创建一个简单的表:

drop table geomtest purge;
create table geomtest ( 
id          number,
name        varchar2(50 char), 
coords      clob, 
coord_geom  sdo_geometry 
);
insert into geomtest (id, name, coords)
values (
2686,
'TX/Mitchell', 
'-101.17416, 32.527592, -101.17417, 32.523998, -101.1836, 32.087082, -100.82121, 32.086479, -100.66497, 32.085278, -100.66024, 32.5252, -101.17416, 32.527592'
);
insert into geomtest (id, name, coords)
values (
2769,
'TX/Yoakum',
'-103.05616, 33.388332, -103.06416, 32.958992, -102.59455, 32.958733, -102.59436, 33.388393, -103.05616, 33.388332'
);
commit;

然后我们用记号赋予器函数来更新几何列:

update geomtest 
set coord_geom = sdo_geometry(2003,4326,null,sdo_elem_info_array(1,1003,1),tokenize(coords));
commit;

检查结果:

SQL> select * from geomtest;
ID NAME        COORDS                                                                                                                                                        COORD_GEOM(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES)
---- ----------- ------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2686 TX/Mitchell -101.17416, 32.527592, -101.17417, 32.523998, -101.1836, 32.087082, -100.82121, 32.086479, -100.66497, 32.085278, -100.66024, 32.5252, -101.17416, 32.527592  SDO_GEOMETRY(2003, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1), SDO_ORDINATE_ARRAY(-101.17416, 32.527592, -101.17417, 32.523998, -101.1836, 32.087082, -100.82121, 32.086479, -100.66497, 32.085278, -100.66024, 32.5252, -101.17416, 32.527592))
2769 TX/Yoakum   -103.05616, 33.388332, -103.06416, 32.958992, -102.59455, 32.958733, -102.59436, 33.388393, -103.05616, 33.388332                                             SDO_GEOMETRY(2003, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1), SDO_ORDINATE_ARRAY(-103.05616, 33.388332, -103.06416, 32.958992, -102.59455, 32.958733, -102.59436, 33.388393, -103.05616, 33.388332))
2 rows selected.

指出

  1. 我使用CLOB列来存储坐标。一个4000字节的字符串太小了,无法容纳任何重要的几何形状(除非你所有的形状都非常简单——只有几个点)。

  2. 如果进行这种字符串到几何的转换,有更有效的方法,但它们意味着您需要使用面向几何的字符串表示法:GeoJSON、WKT、GML。Oracle自然支持这些功能。他们也允许更复杂的结构像多或多边形孔。

编辑:我重写了这个函数,直接返回一个SDO_GEOMETRY对象。这使得它更容易使用:

create or replace function string_to_geom (str clob)
return sdo_geometry
is
s clob := str||',';
i number;
j number;
t sdo_ordinate_array := sdo_ordinate_array();
begin
i := 1;
loop
j := instr(s, ',', i);
exit when j = 0;
t.extend();
t(t.count) := to_number(substr(s,i,j-i));
i := j+1;
end loop;
return sdo_geometry (2003, 4326, null, sdo_elem_info_array (1,1003,1), t);
end;
/
show errors

像这样使用它:

update geomtest 
set coord_geom = string_to_geom(coords);
commit;

最新更新