SQL> SQL> create type typ_point1 as object(obj1 varchar2(3),obj2 varchar2(8)) 2 /
Type created SQL> create type typ_point1newt as table of typ_point1 2 /
Type created
SQL> SQL> SQL> create table test_array( 2 id number, 3 obj typ_point1newt 4 ) 5 nested table obj store as nested_tab return as value 6 /
Table created
SQL> SQL> --造些数据 SQL> SQL> create or replace function f_dividing(i_str in varchar2) return typ_point1newt 2 PIPELINED is 3 begin 4 for i in 1 .. length(i_str) - length(replace(i_str, ','))+1 loop 5 pipe row(typ_point1(i, 6 substr(i_str, 7 instr(','||i_str, ',', 1, i ) , 8 instr(i_str||',', ',', 1, i ) - 9 instr(','||i_str, ',', 1, i ) ))); 10 end loop; 11 return; 12 end f_dividing; 13 /
Function created
SQL> insert into test_array values(1,f_dividing('a,b,c,d'));
1 row inserted
SQL> insert into test_array values(2,f_dividing('1,2,3,4,5'));
1 row inserted
SQL> commit;
Commit complete
SQL> --存储过程操作数组 SQL> set serverout on SQL> SQL> declare 2 v_obj typ_point1newt; --从表中获取数据 3 type typ_varray is varray(100) of varchar2(10); 4 v_array typ_varray:=typ_varray(); --定义数组 5 begin 6 select obj into v_obj from test_array where id=1; 7 for i in 1..v_obj.count loop 8 --存入数组 9 v_array.extend; 10 v_array(i):=v_obj(i).obj2; 11 end loop; 12 --输出数组 13 for j in 1..v_array.count loop 14 dbms_output.put_line(v_array(j)); 15 end loop; 16 end; 17 /
a b c d
PL/SQL procedure successfully completed
SQL>
你好 我还有个比较基础的问题 没弄明白select obj into v_obj from test_array where id=1; 这里如果我想order by v_obj.obj1 该怎么写呢 ? 我写了几种 说不合理的 into_
现在不是排序的问题,是怎么处理数据的问题 当前看起来貌似都不需要用数组变量来处理,在游标中处理即可 for x in (SELECT * FROM TABLE (SELECT OBJ FROM TEST_ARRAY WHERE ID= ? )ORDER BY 时间 ASC) loop处理过程end loop;
我自己写了一个程序 来测试时间排序的 发现如果不用order by 时间也是顺序的 这科学么?。。
那得看你那张表的嵌套表是怎么存的了 在SQL查询中,不同的执行计划可能会使结果出现不同的排序,比如使用的索引,或者全表扫描时记录存储的顺序。若要保证排序,需要加order by
如果要用数组,可以通过游标,把排序后的结果集的值一个一个赋给数组中的元素。再将数组用于计算。只是觉得可能会多此一举 借用我上面的例子select obj into v_obj from test_array where id=1; for i in 1..v_obj.count loop --存入数组 v_array.extend; v_array(i):=v_obj(i).obj2; end loop;这段改成 select obj into v_obj from test_array where id=1; for x in(select rownum rn,obj2 from(select obj2 from table(v_obj) order by obj1)) loop --存入数组 v_array.extend; v_array(x.rn):=x.obj2; end loop;即可实现按obj1的顺序来将obj2存入数组v_array中
SQL> create type typ_point1 as object(obj1 varchar2(3),obj2 varchar2(8))
2 /
Type created
SQL> create type typ_point1newt as table of typ_point1
2 /
Type created
SQL>
SQL>
SQL> create table test_array(
2 id number,
3 obj typ_point1newt
4 )
5 nested table obj store as nested_tab return as value
6 /
Table created
SQL>
SQL> --造些数据
SQL>
SQL> create or replace function f_dividing(i_str in varchar2) return typ_point1newt
2 PIPELINED is
3 begin
4 for i in 1 .. length(i_str) - length(replace(i_str, ','))+1 loop
5 pipe row(typ_point1(i,
6 substr(i_str,
7 instr(','||i_str, ',', 1, i ) ,
8 instr(i_str||',', ',', 1, i ) -
9 instr(','||i_str, ',', 1, i ) )));
10 end loop;
11 return;
12 end f_dividing;
13 /
Function created
SQL> insert into test_array values(1,f_dividing('a,b,c,d'));
1 row inserted
SQL> insert into test_array values(2,f_dividing('1,2,3,4,5'));
1 row inserted
SQL> commit;
Commit complete
SQL> --存储过程操作数组
SQL> set serverout on
SQL>
SQL> declare
2 v_obj typ_point1newt; --从表中获取数据
3 type typ_varray is varray(100) of varchar2(10);
4 v_array typ_varray:=typ_varray(); --定义数组
5 begin
6 select obj into v_obj from test_array where id=1;
7 for i in 1..v_obj.count loop
8 --存入数组
9 v_array.extend;
10 v_array(i):=v_obj(i).obj2;
11 end loop;
12 --输出数组
13 for j in 1..v_array.count loop
14 dbms_output.put_line(v_array(j));
15 end loop;
16 end;
17 /
a
b
c
d
PL/SQL procedure successfully completed
SQL>
这里如果我想order by v_obj.obj1 该怎么写呢 ?
我写了几种 说不合理的 into_
既然只有一个值,就无所谓order排序。如果返回多条记录,select into就会报错,要改成游标方式逐条获取处理
我的设想是 取出来这个typ_point1newt 的里面是有几个typ_point1的类 那我如何才能得到typ_point1里面某个元素的order by呢?
想了半天 想不出来 要是直接用sql查询的话 下面的就是我想要的了,可是into不了
SELECT * FROM TABLE (SELECT OBJ FROM TEST_ARRAY WHERE ID= ? )ORDER BY 时间 ASC
SELECT * FROM TABLE (SELECT OBJ FROM TEST_ARRAY WHERE ID= ? )ORDER BY 时间 ASC这里面的时间就是 typ_point1 里面的一个元素
我上面的例子里,把typ_point1newt 里面是有几个typ_point1的obj2属性打印出来。问题是,排序完以后,你要怎么处理?
多个值是不能into到一个变量里的
SELECT * FROM TABLE (SELECT OBJ FROM TEST_ARRAY WHERE ID= ? )ORDER BY 时间 ASC这里面的时间就是 typ_point1 里面的一个元素不不,用table()处理以后,就是一个M*N的表了
是乱的。我不太清楚,你的最终目标是要用它做什么呢
是乱的。我不太清楚,你的最终目标是要用它做什么呢每个typ_point1newt 作为一个单位 里面有好几个typ_point1 ,就是一个时间段里储存的各种信息,但是时间这个信息是存在typ_point1
里面的 ,当我们使用typ_point1信息 的时候 需要按照时间顺序计算,那么每个typ_point1就应该是顺时序的,不然就乱套啦所以在思考怎么样用成本低的方法给它们排序。
当前看起来貌似都不需要用数组变量来处理,在游标中处理即可
for x in (SELECT * FROM TABLE (SELECT OBJ FROM TEST_ARRAY WHERE ID= ? )ORDER BY 时间 ASC) loop处理过程end loop;
在SQL查询中,不同的执行计划可能会使结果出现不同的排序,比如使用的索引,或者全表扫描时记录存储的顺序。若要保证排序,需要加order by
借用我上面的例子select obj into v_obj from test_array where id=1;
for i in 1..v_obj.count loop
--存入数组
v_array.extend;
v_array(i):=v_obj(i).obj2;
end loop;这段改成
select obj into v_obj from test_array where id=1;
for x in(select rownum rn,obj2 from(select obj2 from table(v_obj) order by obj1)) loop
--存入数组
v_array.extend;
v_array(x.rn):=x.obj2;
end loop;即可实现按obj1的顺序来将obj2存入数组v_array中
对啊 谢谢 这样就可以保证顺序啦。。不过 我还得研究怎么优化整个存储函数 感觉有点慢 对了 我用哪个程序做了一个晚上,估计几千万次select 竟然没有发现不符合时间顺序的 哈哈 感觉可以偷个懒, 不然游标估计得带来1500ms的开学 :D