Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1705817
  • 博文数量: 136
  • 博客积分: 10021
  • 博客等级: 上将
  • 技术积分: 3261
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-22 11:26
文章分类

全部博文(136)

文章存档

2010年(1)

2009年(26)

2008年(109)

我的朋友

分类: Oracle

2008-07-01 15:38:40

Oracle 提供了三种集合:联合数组、嵌套表和 VARRAY 数组,但有的工具或语言并不支持 Oracle 的这种集合处理,所以有时你不得不将集合中的数据插入到真正的表中,然后再使用 SQL 查询出这些数据。对于这样的功能,你可以使用 table() 函数来实现。
 
table() 函数使你可以将集合封装成一个伪表,然后在 SQL 的 from 后面像一个表似的来查询,就像 from 后面可以跟一个子查询一样。下面用嵌套表举几个例子:
 
1. 创建测试表
 
SQL> create table test_yct( id number(2), names tnt_names )
  2  nested table names store as test_yct_names;
 
表已创建。
 
SQL> insert into test_yct values(1, tnt_names('yuechaotian1', 'yuexingtian1', 'jinglitian1'));
 
已创建 1 行。
 
SQL> insert into test_yct values(2, tnt_names('yuechaotian2', 'yuexingtian2', 'jinglitian2'));
 
已创建 1 行。
 
SQL> commit;
 
提交完成。
 
SQL> col names format a60
SQL> select * from test_yct;
 
        ID NAMES
---------- ---------------------------------------------------------
         1 TNT_NAMES('yuechaotian1', 'yuexingtian1', 'jinglitian1')
         2 TNT_NAMES('yuechaotian2', 'yuexingtian2', 'jinglitian2')
 
2. 测试
 
(1)为了将列 test_yct.names 中的数据返回给应用程序,你可以使用 table() 函数:
 
SQL> select y.id, c.* from test_yct y, table(y.names) c;
 
        ID COLUMN_VALUE
---------- --------------------
         1 yuechaotian1
         1 yuexingtian1
         1 jinglitian1
         2 yuechaotian2
         2 yuexingtian2
         2 jinglitian2
 
已选择6行。
 
SQL> select y.id, c.* from test_yct y, table(y.names) c where y.id = 2;
 
        ID COLUMN_VALUE
---------- --------------------
         2 yuechaotian2
         2 yuexingtian2
         2 jinglitian2
 
这个结果集看起来就像是表 test_yct 与集合 table(y.names) 的左外连接一样,而事实确实如此:
 
SQL> insert into test_yct(id) values(3);
 
已创建 1 行。
 
SQL> commit;
 
提交完成。
 
SQL> select y.id, c.* from test_yct y, table(y.names) c;
 
        ID COLUMN_VALUE
---------- --------------------
         1 yuechaotian1
         1 yuexingtian1
         1 jinglitian1
         2 yuechaotian2
         2 yuexingtian2
         2 jinglitian2
 
已选择6行。
 
SQL> select y.id, c.* from test_yct y, table(y.names)(+) c;
 
        ID COLUMN_VALUE
---------- --------------------
         1 yuechaotian1
         1 yuexingtian1
         1 jinglitian1
         2 yuechaotian2
         2 yuexingtian2
         2 jinglitian2
           3
 
已选择7行。
 
注意 COLUMN_VALUE 是一个伪列,你也可以指定该列:
 
SQL> select y.id, c.column_value from test_yct y, table(y.names) c;
 
        ID COLUMN_VALUE
---------- --------------------
         1 yuechaotian1
         1 yuexingtian1
         1 jinglitian1
         2 yuechaotian2
         2 yuexingtian2
         2 jinglitian2
 
已选择6行。
 
table() 函数里也可以是子查询:
 
SQL> select * from table(
  2    select names from test_yct where id = 2
  3  );
 
COLUMN_VALUE
--------------------
yuechaotian2
yuexingtian2
jinglitian2
 
但返回结果必须是一行数据,如果返回多行,那么就会出错:
 
-- 返回所有行:提示错误
SQL> select * from table(
  2    select names from test_yct
  3  );
  select names from test_yct
  *
ERROR 位于第 2 行:
ORA-01427: 单行子查询返回多个行
 
-- 查询 id = 3 的数据,没有结果
SQL> select * from table(
  2    select names from test_yct where id = 3
  3  );
 
未选定行
 
-- 但 id = 3 的条件其实是有结果集的,所以下面的查询仍然会提示错误
SQL> select * from table(
  2    select names from test_yct where id in (2, 3)
  3  );
  select names from test_yct where id in (2, 3)
  *
ERROR 位于第 2 行:
ORA-01427: 单行子查询返回多个行
 
-- 比较一下上下这两个查询
SQL> select * from table(
  2    select names from test_yct where id in (2, 13)
  3  );
 
COLUMN_VALUE
--------------------
yuechaotian2
yuexingtian2
jinglitian2
 
我们最后看看多个集合类型列的例子:
 
SQL> create type tnt_color is table of varchar2(10);
  2  /
 
类型已创建。
 
SQL> alter table test_yct add colors tnt_color
  2    nested table colors store as test_yct_tnt_color;
 
表已更改。
 
SQL> update test_yct set colors=tnt_color('red', 'white') where id = 1;
 
已更新 1 行。
 
SQL> update test_yct set colors=tnt_color('blue', 'green') where id = 2;
 
已更新 1 行。
 
SQL> update test_yct set colors=tnt_color('black') where id = 3;
 
已更新 1 行。
 
SQL> commit;
 
提交完成。
 
SQL> select id, y.*, c.*
  2    from test_yct t, table(t.names) y, table(t.colors) c;
 
        ID COLUMN_VALUE         COLUMN_VAL
---------- -------------------- ----------
         1 yuechaotian1         white
         1 yuechaotian1         red
         1 yuexingtian1          white
         1 yuexingtian1          red
         1 jinglitian1              white
         1 jinglitian1              red
         2 yuechaotian2         green
         2 yuechaotian2         blue
         2 yuexingtian2          green
         2 yuexingtian2          blue
         2 jinglitian2              green
         2 jinglitian2              blue
 
已选择12行。
 
SQL> select id, y.*, c.*
  2    from test_yct t, table(t.names)(+) y, table(t.colors) c;
 
        ID COLUMN_VALUE         COLUMN_VAL
---------- -------------------- ----------
         1 yuechaotian1         white
         1 yuechaotian1         red
         1 yuexingtian1          white
         1 yuexingtian1          red
         1 jinglitian1              white
         1 jinglitian1              red
         2 yuechaotian2         green
         2 yuechaotian2         blue
         2 yuexingtian2          green
         2 yuexingtian2          blue
         2 jinglitian2              green
         2 jinglitian2              blue
         3                                  black
 
已选择13行。
 
 
(2)除了集合类型的列,你也可以使用 table() 将集合变量中的数据封装成一个伪表:
 
SQL> declare
  2   
type tnt_names is table of varchar2(20);
  3   
nt_names tnt_names := tnt_names();
  4    refcur sys_refcursor;
  5    v_name varchar2(20);
  6  begin
  7    nt_names.extend(4);
  8    nt_names(1) := 'yuechaotian';
  9    nt_names(2) := 'yuexingtian';
 10    nt_names(3) := 'oratea';
 11    nt_names(4) := 'guoguo';
 12    open refcur for
select * from table(nt_names);
 13    loop
 14      fetch refcur into v_name;
 15      exit when refcur%notfound;
 16      dbms_output.put_line(v_name);
 17    end loop;
 18  end;
 19  /
  open refcur for select * from table(nt_names);
                                      *
ERROR 位于第 12 行:
ORA-06550: 第 12 行, 第 39 列:
PLS-00642: 在 SQL 语句中不允许使用本地收集类型
ORA-06550: 第 12 行, 第 33 列:
PL/SQL: ORA-22905: 无法从非嵌套表项访问行
ORA-06550: 第 12 行, 第 19 列:
PL/SQL: SQL Statement ignored
 
不好意思,这个匿名块执行出错了。由错误信息我们可以看出来:SQL 中使用的类型,必须是 SCHEMA 级的。我们再试试:
 
SQL> create type tnt_names is table of varchar2(20);
  2  /
 
类型已创建。
 
SQL> declare
  2   
nt_names tnt_names := tnt_names();
  3    refcur sys_refcursor;
  4    v_name varchar2(20);
  5  begin
  6    nt_names.extend(4);
  7    nt_names(1) := 'yuechaotian';
  8    nt_names(2) := 'yuexingtian';
  9    nt_names(3) := 'oratea';
 10    nt_names(4) := 'guoguo';
 11    open refcur for
select * from table(nt_names);
 12    loop
 13      fetch refcur into v_name;
 14      exit when refcur%notfound;
 15      dbms_output.put_line(v_name);
 16    end loop;
 17  end;
 18  /
yuechaotian
yuexingtian
oratea
guoguo
 
PL/SQL 过程已成功完成。
阅读(3863) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~