Oracle 18c如何通过自定义类型成员函数按索引提取varray元素
Oracle 18c:
我创建了一个用户自定义类型及对应的成员函数,功能运行符合预期。
该成员函数返回mdsys.sdo_ordinate_array类型结果,例如MDSYS.SDO_ORDINATE_ARRAY(10, 20, 30, 40, 50, 60)。
初始定义代码如下:
create type my_sdo_geom_type as object ( shape sdo_geometry, member function GetOrdinates(self in my_sdo_geom_type) return mdsys.sdo_ordinate_array deterministic) / create or replace type body my_sdo_geom_type as member function GetOrdinates(self in my_sdo_geom_type) return mdsys.sdo_ordinate_array is begin return shape.sdo_ordinates; end; end; / create table lines (my_sdo_geom_col my_sdo_geom_type); insert into lines (my_sdo_geom_col) values (my_sdo_geom_type(sdo_geometry('linestring(10 20, 30 40, 50 60)'))); select (my_sdo_geom_col).GetOrdinates() from lines
上述代码执行结果:MDSYS.SDO_ORDINATE_ARRAY(10, 20, 30, 40, 50, 60)
现有问题:
上述无参成员函数可正常运行,但实际需求是通过传入坐标索引号返回指定坐标值,而非返回整个varray数组。
尝试写法如下:
select (my_sdo_geom_col).GetOrdinates(1) -- 此处传入参数1而非无参调用 from lines
执行报错:ORA-06553: PLS-306: wrong number or types of arguments in call to 'GETORDINATES'
期望返回结果:10
此前看到相关结论提到:
...SQL语法不支持直接通过索引提取集合元素。
为什么SHAPE.SDO_ORDINATES(1)可在PL/SQL中运行但无法在SQL中使用?
但该结论针对的是对象属性的直接调用场景,并不适用于成员函数场景。
咨询问题
是否存在可行方案,能够通过自定义类型的成员函数按索引号提取varray数组的指定元素?
注:我知晓获取几何对象坐标存在其他实现方式,本次操作仅为学习实验,相关功能需求已向Oracle官方提交建议:
- Oracle Spatial建议:新增SDO_ORDINATES成员函数(支持按索引提取集合元素)
- Oracle通用功能建议:支持SQL语法中按索引提取集合元素
解决方案
报错的核心原因和SQL层面的集合访问限制无关,只是初始定义的GetOrdinates只有无参版本,没有定义接收数字类型索引参数的重载版本,自然会提示参数数量/类型不匹配。
直接给自定义类型重载一个带索引入参的成员函数即可实现需求,修改后的类型定义如下:
create type my_sdo_geom_type as object ( shape sdo_geometry, -- 保留原有无参版本,返回整个坐标数组 member function GetOrdinates(self in my_sdo_geom_type) return mdsys.sdo_ordinate_array deterministic, -- 新增带索引参数的重载版本,返回单个坐标值 member function GetOrdinates(self in my_sdo_geom_type, idx in number) return number deterministic ) / create or replace type body my_sdo_geom_type as member function GetOrdinates(self in my_sdo_geom_type) return mdsys.sdo_ordinate_array is begin return shape.sdo_ordinates; end; member function GetOrdinates(self in my_sdo_geom_type, idx in number) return number is begin -- 可根据业务需求补充索引越界、空值判断逻辑 return shape.sdo_ordinates(idx); end; end; /
类型更新完成后,再执行带参数的查询即可正常返回结果:
select (my_sdo_geom_col).GetOrdinates(1) as first_ordinate from lines
上述查询返回结果为10,完全符合预期。
你提到的“SQL不支持直接通过索引提取集合元素”的限制,仅针对直接访问对象varray属性时用括号取元素的场景,成员函数只要定义了匹配的入参签名,SQL层可以正常传参调用,不存在语法限制。
内容的提问来源于stack exchange,提问作者User1974

