2010-06-29 7 views
7

मैं एक पैकेज कैसे बना सकता हूं जो सीएसवी मानों में पारित होने पर तालिका प्रारूप में परिणाम देता है।सीएसवी को ऑरैकल में तालिका में कनवर्ट करने के लिए कैसे करें

select * from table(schema.mypackage.myfunction('one, two, three')) 

लौटना चाहिए

one 
two 
three 

मैं ask tom से कुछ करने की कोशिश की, लेकिन वह केवल एसक्यूएल प्रकार के साथ काम करता है।

मैं ऑरैकल 11 जी का उपयोग कर रहा हूं। क्या कुछ अंतर्निहित है?

उत्तर

10

निम्नलिखित काम करता है रूप चयन * (स्प्लिटर ('ए, बी, सी, डी')) मेज से

create or replace function splitter(p_str in varchar2) return sys.odcivarchar2list 
is 
v_tab sys.odcivarchar2list:=new sys.odcivarchar2list(); 
begin 
with cte as (select level ind from dual 
connect by 
level <=regexp_count(p_str,',') +1 
) 
select regexp_substr(p_str,'[^,]+',1,ind) 
bulk collect into v_tab 
from cte; 
return v_tab; 
end; 
/
4

अलास, 11 जी में हमें अभी भी एसक्यूएल प्रकारों का उपयोग करके अपने स्वयं के पीएल/एसक्यूएल टोकनकारों को संभालना है। 11 जीआर 2 ओरेकल में हमें सीएसवी स्ट्रिंग में परिणाम जोड़ने के लिए एक समेकित कार्य दिया गया, इसलिए शायद 12i में वे रिवर्स क्षमता प्रदान करेंगे।

आप किसी SQL प्रकार बनाने के लिए नहीं करना चाहते हैं विशेष रूप से आप उपयोग कर सकते हैं में निर्मित SYS.DBMS_DEBUG_VC2COLL, इस तरह:

create or replace function string_tokenizer 
    (p_string in varchar2 
     , p_separator in varchar2 := ',') 
    return sys.dbms_debug_vc2coll 
is 
    return_value SYS.DBMS_DEBUG_VC2COLL; 
    pattern varchar2(250); 
begin 

    pattern := '[^('''||p_separator||''')]+' ; 

    select trim(regexp_substr (p_string, pattern, 1, level)) token 
    bulk collect into return_value 
    from dual 
    where regexp_substr (p_string, pattern, 1, level) is not null 
    connect by regexp_instr (p_string, pattern, 1, level) > 0; 

    return return_value; 

end string_tokenizer; 
/
यहाँ

यह कार्रवाई में है:

SQL> select * from table (string_tokenizer('one, two, three')) 
    2/

COLUMN_VALUE 
---------------------------------------------------------------- 
one 
two 
three 

SQL> 

पावती: यह कोड some code I found on Tanel Poder's blog का एक प्रकार है।

0

मैं 11g साथ खेलने के लिए स्थापित नहीं है, यह आह्वान है, लेकिन वहाँ कॉलम को पंक्तियों/पंक्तियों में कॉलम में कनवर्ट करने के लिए एक PIVOT और UNPIVOT ऑपरेशन है, जो एक अच्छा प्रारंभिक बिंदु हो सकता है।

http://www.oracle.com/technology/pub/articles/oracle-database-11g-top-features/11g-pivot.html

(वास्तव में, कुछ आगे की जांच पड़ताल करने के बाद किया यह इस मामले के लिए उपयुक्त नहीं लगती है - यह एक स्तंभ में वास्तविक पंक्तियों/स्तंभों के साथ काम करता है, लेकिन नहीं डेटा के सेट)।

सीएसवी सूचियों को पीएल/एसक्यूएल टेबल में कनवर्ट करने के लिए डीबीएमएस_UTILITY.comma_to_table और table_to_comma भी है। कुछ सीमाएं हैं (लाइनफेड्स को संभालने, आदि) लेकिन यह एक अच्छा प्रारंभिक बिंदु हो सकता है।

मेरा झुकाव TYPE दृष्टिकोण का उपयोग करना होगा, एक सरल फ़ंक्शन जो comma_to_table करता है, फिर coma_to_table के परिणामस्वरूप प्रत्येक प्रविष्टि के लिए पाइप पंक्ति (दुर्भाग्य से, DBMS_UTILITY.comma_to_table एक प्रक्रिया है इसलिए SQL से कॉल नहीं कर सकता)।

3

यहां नियमित रूप से एसक्यूएल में एक नियमित अभिव्यक्ति matcher का उपयोग करके एक और समाधान है।

SELECT regexp_substr('one,two,three','[^,]+', 1, level) abc 
FROM dual 
CONNECT BY regexp_substr('one,two,three', '[^,]+', 1, level) IS NOT NULL 
2

इष्टतम प्रदर्शन के लिए, स्प्लिटर फ़ंक्शन में पदानुक्रमित (कनेक्ट बाय) प्रश्नों का उपयोग करना सर्वोत्तम है। जब अधिक से अधिक मात्रा में डेटा

CREATE OR REPLACE FUNCTION row2col(p_clob_text IN VARCHAR2) 
    RETURN sys.dbms_debug_vc2coll PIPELINED 
IS 
    next_new_line_indx PLS_INTEGER; 
    remaining_text VARCHAR2(20000); 
    next_piece_for_piping VARCHAR2(20000); 
    BEGIN 

    remaining_text := p_clob_text; 
    LOOP 
     next_new_line_indx := instr(remaining_text, ','); 
     next_piece_for_piping := 
      CASE 
      WHEN next_new_line_indx <> 0 THEN 
       TRIM(SUBSTR(remaining_text, 1, next_new_line_indx-1)) 
      ELSE 
       TRIM(SUBSTR(remaining_text, 1)) 
      END; 

     remaining_text := SUBSTR(remaining_text, next_new_line_indx+1); 
     PIPE ROW(next_piece_for_piping); 
     EXIT WHEN next_new_line_indx = 0 OR remaining_text IS NULL; 
    END LOOP; 
    RETURN; 
    END row2col; 
/

इस प्रदर्शन अंतर नीचे देखा जा सकता है के लिए लागू किया

निम्नलिखित स्प्लिटर समारोह एक अच्छा सौदा बेहतर प्रदर्शन करती है (मैं समारोह विभाजक इस्तेमाल किया के रूप में इस चर्चा में पहले दिया गया था)।

SQL> SET TIMING ON 
SQL> 
SQL> WITH SRC AS (
    2 SELECT rownum||',a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z'||rownum txt 
    3 FROM DUAL 
    4 CONNECT BY LEVEL <=10000 
    5 ) 
    6 SELECT NULL 
    7 FROM SRC, TABLE(SYSTEM.row2col(txt)) t 
    8 HAVING MAX(t.column_value) > 'zzz' 
    9 ; 

no rows selected 

Elapsed: 00:00:00.93 
SQL> 
SQL> WITH SRC AS (
    2 SELECT rownum||',a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z'||rownum txt 
    3 FROM DUAL 
    4 CONNECT BY LEVEL <=10000 
    5 ) 
    6 SELECT NULL 
    7 FROM SRC, TABLE(splitter(txt)) t 
    8 HAVING MAX(t.column_value) > 'zzz' 
    9 ; 

no rows selected 

Elapsed: 00:00:14.90 
SQL> 
SQL> SET TIMING OFF 
SQL> 
संबंधित मुद्दे