2011-09-07 47 views

回答

0

我通常更喜歡在這種情況下使用MULTISET運算符。

下面的解決方案並不完美,因爲您必須標記字符串以使用MULTISET運算符,但是如果您將列表作爲集合,那麼這將非常容易(或者如果您已經有共同的標記器)。 (下面的標記生成器是不是很快。)

DECLARE 
    TYPE VARCHARTABLE IS TABLE OF VARCHAR2(2000); 

    A VARCHAR2(32767) := 'a1, b4, g3, h6, t8, a0'; 
    B VARCHAR2(32767) := 'b4, h6, a0, t8, a1'; 

    onlyInA VARCHARTABLE; 
    onlyInB VARCHARTABLE; 

    FUNCTION tokenize(v IN VARCHAR2) 
    RETURN VARCHARTABLE 
    IS 
     mReturn VARCHARTABLE := VARCHARTABLE(); 
     mTemp VARCHAR2(2000); 
     mChar VARCHAR2(1); 
     mIdx INTEGER := 1; 

     PROCEDURE appendToken(token IN VARCHAR2) 
     IS 
     BEGIN 
     IF TRIM(token) IS NOT NULL THEN 
      mReturn.EXTEND(1); 
      mReturn(mReturn.LAST) := TRIM(token); 
     END IF; 
     END appendToken; 
    BEGIN 
     LOOP 
     mChar := SUBSTR(v, mIdx, 1); 

     IF mChar = ',' THEN 
       appendToken(mTemp); 
       mTemp := NULL; 
     ELSIF mChar IS NULL THEN 
      appendToken(mTemp); 
      EXIT; 
     ELSE 
      mTemp := mTemp || mChar; 
     END IF; 

     mIdx := mIdx + 1; 
     END LOOP; 

     RETURN mReturn; 
    END tokenize; 

    FUNCTION toVarchar(v IN VARCHARTABLE) 
    RETURN VARCHAR2 
    IS 
    mReturn VARCHAR2(32767); 
    mIdx INTEGER := 0; 
    BEGIN 
    mIdx := v.FIRST; 

    WHILE mIdx IS NOT NULL LOOP 
     IF mReturn IS NOT NULL THEN 
      mReturn := mReturn || ','; 
     END IF; 
     mReturn := mReturn || v(mIdx); 

     mIdx := v.NEXT(mIdx); 
    END LOOP; 

    RETURN mReturn; 
    END toVarchar; 
BEGIN 
    onlyInA := tokenize(A) MULTISET EXCEPT tokenize(B); 
    onlyInB := tokenize(B) MULTISET EXCEPT tokenize(A); 

    DBMS_OUTPUT.put_line('Only in A : ' || toVarchar(onlyInA)); 
    DBMS_OUTPUT.put_line('Only in B : ' || toVarchar(onlyInB)); 
END; 
+0

太棒了 - 謝謝! – user813345

1

不確定優雅,但這樣的工作:

WITH t1 AS (SELECT 'a1, b4, g3, h6, t8, a0' str FROM dual), 
    t2 AS (SELECT 'b4, h6, a0, t8, a1' str  FROM dual) 
-- 
SELECT val 
    FROM t1, 
     xmltable('/root/e/text()' 
     passing xmltype('<root><e>' || 
         replace(t1.str,', ','</e><e>') || 
         '</e></root>') 
     columns val varchar2(10) path '/') 
MINUS 
SELECT val 
    FROM t2, 
     xmltable('/root/e/text()' 
     passing xmltype('<root><e>' || 
         replace(t2.str,', ','</e><e>') || 
         '</e></root>') 
     columns val varchar2(10) path '/') 

希望這可以幫助

0

如果你知道他們將要逗號和/或空格分隔那麼這將工作,是簡單了很多。

create or replace function compare_strings (PString1 char, Pstring2 char) return char is 

    v_string1 varchar2(100) := replace(replace(Pstring1,',',''),' ',''); 
    v_string2 varchar2(100) := replace(replace(Pstring2,',',''),' ',''); 

begin 

    if replace(translate(v_string1, v_string2, ' '), ' ', '') is null then 
     return replace(translate(v_string2, v_string1, ' '), ' ', '') ; 
    else 
     return replace(translate(v_string1, v_string2, ' '), ' ', ''); 
    end if; 

end; 

編輯:改變返回字符串。

+0

但是,這實際上並沒有返回差異 - 只是如果有差異? – user813345

+0

我改變了它。 – Ben