首先,您的多边形格式不正确:它没有关闭。对于多边形,最后一个点必须与第一个点匹配。您可以通过执行以下操作来检测错误:
SQL> select sdo_geom.validate_geometry_with_context (SDO_GEOMETRY(2003, 8307, null, SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY(10,10, 10,-10, -10,-10, -10,10)), 0.05) from dual;
13348 [Element <1>] [Ring <1>]
1 row selected.
ORA-13348: polygon boundary is not closed
一旦你更正了,你会得到一个不同的错误:
SQL> select sdo_geom.validate_geometry_with_context (SDO_GEOMETRY(2003, 8307, null, SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY(10,10, 10,-10, -10,-10, -10,10, 10,10)), 0.05) from dual;
13367 [Element <1>] [Ring <1>]
1 row selected.
ORA-13367: wrong orientation for interior/exterior rings
对于多边形,点必须处于逆时针方向。更正后,多边形是正确的:
SQL> select sdo_geom.validate_geometry_with_context (SDO_GEOMETRY(2003, 8307, null, SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY(10,10, -10,10, -10,-10, 10,-10, 10,10)), 0.05) from dual;
TRUE
1 row selected.
并且查询正常工作。这是一个例子:
create table t1 (id number, note varchar2(20), geom sdo_geometry);
insert into t1 (id, note, geom)
values (
1,
'Not closed',
SDO_GEOMETRY(2003, 8307, null, SDO_ELEM_INFO_ARRAY(1,1003,1), SDO_ORDINATE_ARRAY(10,10, 10,-10, -10,-10, -10,10))
);
insert into t1 (id, note, geom)
values (
2,
'Wrong orientation',
SDO_GEOMETRY(2003, 8307, null, SDO_ELEM_INFO_ARRAY(1,1003,1), SDO_ORDINATE_ARRAY(10,10, 10,-10, -10,-10, -10,10, 10,10))
);
insert into t1 (id, note, geom)
values (
3,
'Valid',
SDO_GEOMETRY(2003, 8307, null, SDO_ELEM_INFO_ARRAY(1,1003,1), SDO_ORDINATE_ARRAY(10,10, -10,10, -10,-10, 10,-10, 10,10))
);
commit;
insert into user_sdo_geom_metadata (table_name, column_name, diminfo, srid)
values (
'T1',
'GEOM',
sdo_dim_array (
sdo_dim_element ('Long',-180,180,0.5),
sdo_dim_element ('Lat',-90,90,0.5)
),
8307
);
commit;
create index t1_sx on t1 (geom) indextype is mdsys.spatial_index;
测试表包含多边形的三个变体。让我们尝试一个查询:
select *
from t1
where sdo_relate(
geom,
SDO_GEOMETRY('MULTIPOINT((0 0))',8307),
'mask=anyinteract'
) = 'TRUE';
返回正确的结果:只有有效的多边形被正确识别为包含您的点:
ID NOTE GEOM(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES)
---------- -------------------- -------------------------------------------------------------------------------
3 Valid SDO_GEOMETRY(2003, 8307, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1), SDO_ORDINATE_ARRAY(10, 10, -10, 10, -10, -10, 10, -10, 10, 10))
1 row selected.
至于多边形中点的 ANYINTERACT 和 CONTAINS 之间的差异,它会影响多边形边界上的那些点(或更准确地说,在边界的公差范围内)。ANYINTERACT 搜索会返回这些。CONTAINS/INSIDE 搜索不会。
这可能很重要,例如,当您想要将点分布到多边形(如销售区域中的客户点位置)并且某些客户位置点恰好落在相邻区域之间的边界上时:ANYINTERACT 搜索将报告这些位置在两个区域中. INSIDE 搜索将报告它们都不在.
最后,为您的查询使用更简单的语法:
select *
from t1
where sdo_anyinteract(
geom,
SDO_GEOMETRY('MULTIPOINT((0 0))',8307)
) = 'TRUE';
有关如何获取与错误代码(如 13348)相对应的消息的一些信息。我通常使用这种技术:
set serveroutput on
exec dbms_output.put_line(sqlerrm(-13348))
这将打印出完整的错误消息。请注意,您必须使用减号传递错误。