1

当我做

SQL> select cast( csv_convert.to_text( 'ABC,ACD,DE' ) as t_tbl_of_text ) from dual;
select cast( csv_convert.to_text( 'ABC,ACD,DE' ) as t_tbl_of_text ) from dual
             *
**ERROR at line 1:
ORA-00902: invalid datatype**


create or replace package csv_convert is
   type t_tbl_of_text is table of varchar2(32767);
    function to_text( p_str in varchar2 )
           return t_tbl_of_text;
end csv_convert;
/

Package created.


create or replace package body csv_convert as
    function to_text(p_str in varchar2 ) return t_tbl_of_text is
           l_data    t_tbl_of_text := t_tbl_of_text();
           l_str     varchar2(32767) default p_str || ',';
           l_n       number;
           begin
                   loop
                           l_n := instr( l_str, ',' );
                           exit when (nvl(l_n,0) = 0);
                           l_data.extend;
                           l_data( l_data.count ) := trim(substr(l_str,1,l_n-1));
                           l_str := substr( l_str, l_n+1 );
                   end loop;
           return l_data;
           end to_text;
end csv_convert;
  /
4

1 回答 1

0

包中定义的 PL/SQL 类型对 SQL 语句是不可见的:它们是纯 PLSQL 构造,SQL 语言不能直接访问它们。可以观察到相同的现象VARCHAR2:SQL 可以定义/访问VARCHAR2多达 4000 个字节,而 PL/SQL 将能够处理多达 32767 个字节的字符串。

解决方法是使用 SQL 类型,例如 VARRAY 的嵌套表:

SQL> CREATE TYPE obj_tbl_of_text IS TABLE of varchar2(4000);
  2  /

Type created

SQL> CREATE OR REPLACE PACKAGE csv_convert IS
  2     FUNCTION to_text(p_str IN VARCHAR2) RETURN obj_tbl_of_text;
  3  END csv_convert;
  4  /

Package created

SQL> CREATE OR REPLACE PACKAGE BODY csv_convert AS
  2     FUNCTION to_text(p_str IN VARCHAR2) RETURN obj_tbl_of_text IS
  3        l_data obj_tbl_of_text := obj_tbl_of_text();
  4        l_str  VARCHAR2(32767) DEFAULT p_str || ',';
  5        l_n    NUMBER;
  6     BEGIN
  7        LOOP
  8           l_n := instr(l_str, ',');
  9           EXIT WHEN(nvl(l_n, 0) = 0);
 10           l_data.EXTEND;
 11           l_data(l_data.COUNT) := TRIM(substr(l_str, 1, l_n - 1));
 12           l_str := substr(l_str, l_n + 1);
 13        END LOOP;
 14        RETURN l_data;
 15     END to_text;
 16  END csv_convert;
 17  /

Package body created

现在可以直接在 SQL 中调用 pacakge(即使没有 CAST):

SQL> select csv_convert.to_text( 'ABC,ACD,DE' ) from dual;

CSV_CONVERT.TO_TEXT('ABC,ACD,DE')
--------------------------------------------------------------------------------
OBJ_TBL_OF_TEXT('ABC', 'ACD', 'DE')
于 2012-12-18T09:08:19.727 回答