数据库入门 MSSQL MySQLOracle Sybase DB2 Informix 其它数据库
返回首页
当前位置: 冰山软件站 > 数据库 > Oracle >

PL/SQL collection— table() 函数使用

时间:2008-07-02来源:blog.chinaunix.net 作者:yuechaot… 点击:
Oracle 提供了三种集合:联合数组、嵌套表和 VARRAY 数组,但有的工具或语言并不支持 Oracle 的这种集合处理,所以有时你不得不将集合中的数据插入到真正的表中,然后再使用 SQL 查询出

  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 过程已成功完成。

顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名:密码: 验证码:点击我更换图片
推荐内容