我正在研究 Oracle 中的数组支持,并遇到了有关 SQL 查询中数组访问的障碍。我正在使用以下架构:
create type smallintarray as varray(10) of number(3,0);
create table tbl (
id number(19,0) not null,
the_array smallintarray,
primary key (id)
);
我想做的是获取 id 和第一个元素,即数组的索引 1 处的元素。在 PostgreSQL 中我可以写
select id, the_array[1] from tbl t
但我不知道如何在 Oracle 中做到这一点。我读到,通过索引进行数组访问只能在 PL/SQL 中进行,如果我可以返回一个“修饰游标”以通过 JDBC 实现相同的结果,那就太好了,但我不知道这是否可能。
DECLARE
c1 SYS_REFCURSOR;
varr smallintarray2;
BEGIN
OPEN c1 FOR SELECT t.id, t.THE_ARRAY from tbl t;
-- SELECT t.THE_ARRAY INTO varr FROM table_with_enum_arrays2 t;
-- return a "decorated cursor" with varr(1) at select item position 1
dbms_sql.return_result(c1);
END;
您可以使用简单的 SQL 来完成此操作;它不漂亮,但确实有效。您希望 Oracle 有语法来向程序员隐藏这一点(也许确实如此,至少在最新版本中;我仍然停留在 12.2)。
select t.id, q.array_element
from tbl t cross apply
( select column_value as array_element,
rownum as ord
from table(the_array)
) q
where ord = 1
;
编辑 如果通过
table
运算符生成元素的顺序是一个问题,您可以执行类似的操作(在 Oracle 12.1 及更高版本中;否则该函数不能成为查询本身的一部分,但可以是自己定义):
with
function select_element(arr smallintarray, i integer)
return number
as
begin
return arr(i);
end;
select id, select_element(the_array, 1) as the_array_1
from tbl
/
首先,请不要在生产中这样做。使用表而不是在表中存储数组。
回答你的问题是使用列作为表源
SELECT t.id, ta.*
from tbl t,
table(t.THE_ARRAY) ta
order by column_value
-- offset 1 row -- in case if sometime you'll need to skip a row
fetch first 1 row only;
UPD:至于对数组进行排序,我只能说使用 2asc/desc" 参数为我提供了预期的结果 - 它已按升序或降序排序。
UPD2:找到了一个很酷的链接来描述性能可能发生的问题
您可以使用名为
SYS_OP_CEG
的未记录函数在 Oracle SQL 中执行此操作:
SELECT SYS_OP_CEG
( sys.odcivarchar2list('Dave','Dee','Dozy','Beaky','Mick','Titch')
, 3 ) AS third_item
FROM dual;
SYS_OP_CEG
采用一个变量数组和一个从一开始的索引作为参数。上面的示例使用 varchar2
的变量并打印 Dozy
,这是第三个元素。
是的,它不如 PostgreSQL 简单。
P.S:我刚刚使用 Oracle 19 进行了测试,但预计它可以与 Oracle 9.2 及更高版本一起使用。