【问题标题】:Oracle Spatial search query error for SDO_WITHIN_DISTANCE (lat/long based)SDO_WITHIN_DISTANCE 的 Oracle Spatial 搜索查询错误(基于纬度/经度)
【发布时间】:2020-10-28 21:39:27
【问题描述】:

我需要基于纬度和经度对执行基于位置的搜索,以找出给定 KM 的半径/距离内商店的附近位置。

  • 我将(肯定)使用 Oracle 的 SDO_GEOMETRY 来搜索位置。
  • 此外,表结构是基于父子表的,这样存储地址(zip、lat/long)在父表中,而存储详细信息(姓名、联系人等)在子表中。
  • 这是为了确保我们没有多余的数据(因为多个商店可以有相同的纬度/经度,并且通过一些暗魔法相同的地址)

我有以下情况(提供表格):

版本 - Oracle Database 12c Enterprise Edition Release 12.2.0.1.0

  • 表:STORE_LOCATION
CREATE TABLE STORE_LOCATE
(
    ID                  NUMBER                 DEFAULT STORE_LOCATE.nextval,
    POSTAL_CODE         VARCHAR2(18)           NOT NULL,
    ADDRESS             VARCHAR2(382)          NOT NULL,
    GEO_LOCATION        SDO_GEOMETRY           NOT NULL
);

  • 表:STORE_DETAIL
CREATE TABLE STORE_DETAIL
(
    ID                    NUMBER                   DEFAULT STORE_DETAIL_SEQ.nextval,
    STORE_CODE            VARCHAR2(20)             NOT NULL,
    STORE_NAME            VARCHAR2(150)            NOT NULL,
    IS_ACTIVE             NUMBER(3)                DEFAULT 0 NOT NULL,
    fk_store_locate_id  INT                        NOT NULL. -- FK to ID of parent
);

我已在父项中插入数据:

INSERT INTO STORE_LOCATE (ZIP, ADDRESS, GEO_LOCATION) VALUES
  ('567875', '84 Paddar Road', 
     SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE (80.34234431,26.12354422, NULL), NULL, NULL));

同样,子表也有条目:

INSERT INTO STORE_DETAIL (STORE_CODE, STORE_NAME, FK_STORE_LOCATION_ID) VALUES
  ('ST01', 'STORE 1', 1);
  • 所以,现在当用户向我分享他的位置(纬度/经度)时,我需要搜索指定半径内所有附近的商店位置。

我尝试了以下查询,但遇到了错误:

SELECT  
   s.store_code,
   s.store_name,
   loc.zip,
   loc.address,
   loc.geo_location
FROM store_detail s, 
   store_locate loc
where MDSYS.SDO_WITHIN_DISTANCE(loc.geo_location,
(MDSYS.SDO_GEOMETRY(2001, 8307, 
   MDSYS.SDO_POINT_TYPE(80.21456732,26.23117864, NULL) ,NULL, NULL)), 
     'distance=1000 unit=KM') = 'TRUE';

得到以下错误:

ORA-29900: operator binding does not exist
ORA-06553: PLS-306: wrong number or types of arguments in call to 'SDO_WITHIN_DISTANCE'
29900. 00000 -  "operator binding does not exist"
*Cause:    There is no binding for the current usage of the operator.
*Action:   Change the operator arguments to match any of the existing
           bindings or add a new binding to the operator.

我现在想了一会儿,但徒劳无功。

参考:

问题:

  • 这是在 Oracle SQL 上执行位置搜索的正确方法吗?
  • 如果以上不正确,有没有其他办法?

【问题讨论】:

    标签: database oracle geospatial oracle-spatial


    【解决方案1】:

    您的代码中有许多语法错误(POSTAL_CODE 称为 ZIP 等) 这是更正后的示例(为简单起见,我还删除了序列)

    CREATE TABLE STORE_LOCATE (
        ID                  NUMBER                 primary key,
        POSTAL_CODE         VARCHAR2(18)           NOT NULL,
        ADDRESS             VARCHAR2(382)          NOT NULL,
        GEO_LOCATION        SDO_GEOMETRY           NOT NULL
    );
    CREATE TABLE STORE_DETAIL (
        ID                    NUMBER                   primary key,
        STORE_CODE            VARCHAR2(20)             NOT NULL,
        STORE_NAME            VARCHAR2(150)            NOT NULL,
        IS_ACTIVE             NUMBER(3)                DEFAULT 0 NOT NULL,
        fk_store_locate_id    INT                      NOT NULL references STORE_LOCATE
    );
    INSERT INTO STORE_LOCATE (ID, POSTAL_CODE, ADDRESS, GEO_LOCATION) VALUES (1, '567875', '84 Paddar Road', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE (80.34234431,26.12354422, NULL), NULL, NULL));
    INSERT INTO STORE_DETAIL (ID, STORE_CODE, STORE_NAME, FK_STORE_LOCATE_ID) VALUES (1001,'ST01', 'STORE 1', 1);
    commit;
    

    这里正在运行您的查询:

    SELECT  
       s.store_code,
       s.store_name,
       loc.postal_code,
       loc.address,
       loc.geo_location
    FROM store_detail s, store_locate loc
    where SDO_WITHIN_DISTANCE(
      loc.geo_location,
      SDO_GEOMETRY(2001, 8307, 
        SDO_POINT_TYPE(80.21456732,26.23117864, NULL),NULL, NULL
      ), 
      'distance=1000 unit=KM'
    ) = 'TRUE';
    
    STORE_ STORE_NAME POSTAL ADDRESS              GEO_LOCATION(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES
    ------ ---------- ------ -------------------- ----------------------------------------------------------------------------------
    ST01   STORE 1    567875 84 Paddar Road       SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE(80.3423443, 26.1235442, NULL), NULL, NULL)
    
    1 row selected.
    

    您收到的错误可能意味着您的数据库中未安装或未正确安装 Oracle Spatial。您使用的确切数据库版本是什么?

    重要提示:

    这些查询确实需要 GEO_LOCATION 列上的​​空间索引。如果没有,查询在 12.1 之前的版本中会被拒绝。从 12.2 及更高版本开始,查询将运行,但一旦位置数量超过几百个,查询就会非常慢。一旦进入100000以上,就会非常慢。

    详情请见https://docs.oracle.com/en/database/oracle/oracle-database/19/spatl/indexing-querying-spatial-data.html#GUID-07129836-0DAE-4BCC-B290-942C456AE2EA

    【讨论】:

    • 谢谢!我很抱歉 ZIP。除此之外,我尝试了多种语法,但发布了这个。搜索查询中是否有任何语法错误?我只看到一个支架被移除。告诉我!
    • 版本 - Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
    • 你的语法是正确的。我只是为了可读性(出于品味)而对其进行了一些不同的布局,并更正了列名的差异。它应该可以工作(并且对我有用)。如果它不在您的数据库中,我只能认为您的空间安装有问题
    • 等一下。我想到了什么。您如何连接到数据库 - 哪个用户?确保您以普通用户身份连接。不是系统。绝对不是SYS。使用 SYS 的副作用可以解释你所看到的
    • 感谢您的帮助。是的,我以普通用户身份连接(没有管理员权限或系统权限)我怀疑它与安装有关。我将在内部与团队讨论。再次感谢!
    猜你喜欢
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-19
    • 2013-12-29
    • 2012-04-19
    • 1970-01-01
    相关资源
    最近更新 更多