当前位置: 首页 > 知识库问答 >
问题:

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

茹正初
2023-03-14

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

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

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

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

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

名为GEOMTEST的测试表由NAME varchar 2(50)COORDS varchar 2(4000)COORD _ GEOM SDO _ GEOMETRY组成

我用英国威尔士的“羊毛衫湾”这个有趣的区域来填充这个名字。COORDS是我在varchar2中存储为数组的多边形。它是从CSV文件导入的。COORD_GEOM是我希望将COORDS的内容转换成的内容。

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

将值(SDO_GEOMETRY(20034326,null,SDO_ ELEM_INFO_ARRAY(11003,1))和SDOUOr座标_;

我使用Toad作为我的客户机,错误是“错误:第18行。第120列,第18行结尾,第125列:找到‘值’:保留字不能用作标识符。

我假设这与我在INSERT语句的SDO_。

我很感激任何建议,

多谢

肖恩

共有1个答案

弘涛
2023-03-14

不幸的是,您不能将包含数字的字符串直接传递给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.

笔记

>

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

    如果进行字符串到几何的转换,有更有效的方法,但它们意味着您使用面向几何的字符串符号: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;
    

  •  类似资料:
    • 问题内容: 我有一个包含4列的表格:项目,年份,月份,金额。Amount的某些值是null,当发生这种情况时,我想用以前的非null的Amount值来填充这些值。当只有一个空值时,我可以使用LAG函数轻松地做到这一点,但是当连续有多个空值时,我不确定如何处理它。以下是该表的外观示例,其中添加了要在查询中添加的内容的列: 我有两个想法,我似乎无法投入工作来实现自己想要的东西。首先,我要使用LAG,但

    • 我有两个表:包含5列(col1、col2、col3、col4、val1)的表1和包含5列(col1、col2、col3、col4、val2)的表2。1.表1.val1不包含任何值。2.对于表1和表2来说,col1、col2、col3和col4是相同的,它们是主键。 我想做的是,当table1.col1=table2.col1和table1.col2=table2.col2和table1.col3=

    • 我正在使用Oracle和Oracle Forms Builder(中间件)两者11gR2。我正在创建一个采购记录系统。我有以下2个表格。 我的计划:所有产品详细信息都将在产品表中。购买表将仅用于输入购买信息。此表无法输入任何新产品。如果有任何新名称,则必须首先将该信息输入到产品表中。这样我就可以减少重复的名字。现在我在表单中与prodname(产品名称)列有关。 我仅使用购买表创建表单。此表没有p

    • 我有两个表TABLE_A,列名为COLUMN1 COLUMN2 COLUMN3 COLUMN 4 COLUM5 abc def ghi jkl mno 123 456 789 001 121 TABLE_B列名为COLUMN6 COLUMN7,其数据为 专栏5 124 第4列bca 第3列aaa 列5 BBB 所以我将Table_A的列名作为Table_B中的数据 所以我想在一个查询中做这样的事情

    • 问题内容: 我有一个属于表空间 报告 的分区表。我想将其移至表空间 记录 。 一种可能性是删除表并在新表空间中重新创建它,但这对我来说不是一个选择,因为表中有数据需要在移动后幸存。 我首先使用以下命令检查分区是否真正属于表空间报告: 然后我只是尝试: 但这给了我错误ORA-145111``无法对已分区的对象执行操作’‘。 然后我发现我可以使用以下方法移动单个分区: 但是由于该表有60个分区(基于日

    • 问题内容: 我已经阅读了有关创建触发器的Oracle文档,并且正在按照显示的方式进行操作,但是这是行不通的。我的目标是使用出现在TPM_TRAININGPLAN表中的最小STARTDATE更新TPM_PROJECT表。因此,每次有人更新TPM_TRAININGPLAN中的STARTDATE列时,我都想更新TPM_PROJECT表。这是我正在尝试的方法: 创建的触发器没有错误,但是我得到了警告: 当