2011-11-18 36 views
1

可能重複:
How to best split csv strings in oracle 9i轉換T-SQL函數PL/SQL

你能幫我轉換下面的T-SQL funcntion到Oracle。該功能將類似

service|nvretail;language|de;yyyy|2011; 

的字符串轉換爲表格。

我遇到的主要問題是臨時表的使用。我在Oracle中找不到任何等價物。

CREATE FUNCTION [dbo].[TF_ConvertPara] 
( 
    @parastringNVARCHAR(max) 
) 
RETURNS @para TABLE 
(
    [Key] varchar(max), 
    [Value] varchar(max) 
) 
begin 
    DECLARE @NextString NVARCHAR(40) 
    DECLARE @Pos1  INT 
    DECLARE @Pos2  INT 
    DECLARE @NextPos INT 
    DECLARE @Delimiter1 NCHAR=';' 
    DECLARE @Delimiter2 NCHAR='|' 

    if substring(@paraString, len(@paraString) - 1, 1) <> @Delimiter1 
    SET @paraString = @paraString + @Delimiter1 

    SET @Pos1 = charindex(@Delimiter1, @paraString) 
    WHILE (@pos1 <> 0) 
    BEGIN 
    SET @NextString = substring(@paraString, 1, @Pos1 - 1) 
    SET @paraString = substring(@paraString, @pos1 + 1, len(@paraString)) 
    SET @pos1 = charindex(@Delimiter1, @paraString) 

    SET @Pos2 = charindex(@Delimiter2, @NextString) 
    if (@Pos2 > 0) 
    begin 
     insert into @para 
     values 
     (substring(@NextString, 1, @Pos2 - 1), 
     substring(@NextString, @Pos2 + 1, len(@NextString))) 
    end 
    END 
    return; 
end 

在此先感謝您。

+0

@Lieven,OP沒有指定Oracle 9i。 Oracle 10g和11g比9i有更強大的功能來分割字符串。 – Ollie

+1

@Ollie - 你是對的,但實質上,TSQL所做的就是分割一個字符串。在任何特定環境下都可以找到很多示例。 +1 *你的*答案btw。 –

+0

看到這個以及:http://stackoverflow.com/questions/8099430/does-oracle-provide-the-way-of-returning-multiple-substrings-from-a-string-clob/8100085#8100085 –

回答

2

要返回的鍵值對,這個怎麼樣(適用於Oracle 10g及以上):

CREATE OR REPLACE FUNCTION csv_to_rows(mycsv IN VARCHAR2) 
RETURN sys_refcursor 
AS 
    c SYS_REFCURSOR; 
BEGIN 
    OPEN c FOR   
     SELECT SUBSTR(element,1,INSTR(element,'|')-1) as key , 
     SUBSTR(element,INSTR(element,'|')+1,99999) as val 
     FROM (
      SELECT REGEXP_SUBSTR(mycsv,'[^;]+',1,LEVEL) element   
       FROM dual  
       CONNECT BY LEVEL < LENGTH(REGEXP_REPLACE(mycsv,'[^;]+')) + 1 
      ); 
    RETURN c;  
END; 

並查看結果:

DECLARE 
    c SYS_REFCURSOR; 
    akey VARCHAR2(100); 
    aval VARCHAR2(100); 
BEGIN 
c := csv_to_rows('service|nvretail;language|de;yyyy|2011'); 
LOOP 
    FETCH c into akey,aval; 
    EXIT WHEN c%NOTFOUND; 

    dbms_output.put_line('Key : '||akey || ' Value : '||aval); 
END LOOP;  
END; 

這應該給你

Key : service Value : nvretail 
Key : language Value : de 
Key : yyyy  Value : 2011 
+0

酷!這工作正常! – llasarov

3

如果你正在尋找您的字符串的標記恢復爲行,那麼你可以做到這一切在一個單一的SQL查詢:

WITH t AS (SELECT 'service|nvretail;language|de;yyyy|2011;' as val FROM dual) 
SELECT row_output 
    FROM t, 
     XMLTABLE('/root/e/text()' 
      PASSING xmltype('<root><e>' || 
          REGEXP_REPLACE (t.val, '(;|\|)', '</e><e>') || 
          '</e></root>') 
        COLUMNS row_output VARCHAR2(4000) PATH '/'); 

返回:

service 
nvretail 
language 
de  
yyyy  
2011 

如果您希望將這些行放在表中,然後將SQL包裝在一個簡單的函數中,以返回內存表或將記錄插入到數據庫表中,無論您需要什麼。

這裏是返回的VARCHAR2記錄的表(集合)函數的例子:

CREATE OR REPLACE 
FUNCTION str_to_table (
    p_input_str IN VARCHAR2 
) 
RETURN DBMS_SQL.VARCHAR2_TABLE 
IS 
    CURSOR str_to_rows (
     cp_str IN VARCHAR2 
    ) 
    IS 
     SELECT row_output 
     FROM (SELECT cp_str as val FROM dual) t, 
      XMLTABLE('/root/e/text()' 
       PASSING xmltype('<root><e>' || 
         REGEXP_REPLACE(t.val, '(;|\|)', '</e><e>') || 
           '</e></root>') 
         COLUMNS row_output VARCHAR2(4000) PATH '/'); 

    varchar_tab DBMS_SQL.VARCHAR2_TABLE; 
BEGIN 
    OPEN str_to_rows(p_input_str); 
    FETCH str_to_rows BULK COLLECT INTO varchar_tab; 
    CLOSE str_to_rows; 
    -- 
    RETURN varchar_tab; 
EXCEPTION 
    WHEN others 
    THEN 
     IF str_to_rows%ISOPEN 
     THEN 
     CLOSE str_to_rows; 
     END IF; 
     RAISE; 
END str_to_table; 

這是未經測試所以有可能是一對夫婦的語法錯誤,但它應該是prety接近。

要返回一個REF CURSOR:

CREATE OR REPLACE 
FUNCTION str_to_table (
    p_input_str IN VARCHAR2 
) 
RETURN sys_refcursor 
IS      
    cur SYS_REFCURSOR; 
BEGIN 
    OPEN cur 
    FOR SELECT row_output 
      FROM (SELECT p_input_str as val FROM dual) t, 
       XMLTABLE('/root/e/text()' 
         PASSING xmltype('<root><e>' || 
         REGEXP_REPLACE (t.val, '(;|\|)', '</e><e>') || 
              '</e></root>') 
         COLUMNS row_output VARCHAR2(4000) PATH '/'); 
    -- 
    RETURN cur; 
END str_to_table; 

希望它可以幫助...

+0

奧利,謝謝你的答案,但你可以修改函數,因此它返回一個REF CURSOR。 – llasarov

+0

完成,看到上面編輯的答案... – Ollie