2012-12-18 13 views
1

當我在包中定義PLSQL無效的數據類型,即使在鑄造後,爲什麼

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; 
/

回答

0

PL/SQL類型是不可見的SQL語句:他們是純粹的PLSQL結構和SQL語言不能直接訪問它們。使用VARCHAR2可以觀察到同樣的現象:SQL可以定義/訪問多達4000字節的VARCHAR2,而PL/SQL將能夠處理多達32767字節的字符串。

的解決方法是使用SQL類型,如可變數組的嵌套的表格:

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')