【问题标题】:Difference between two unordered delimited strings in PL/SQLPL/SQL 中两个无序分隔字符串之间的区别
【发布时间】:2011-11-12 14:08:35
【问题描述】:

有没有一种简单优雅的方法来使用 PL/SQL 返回 Oracle 中两个无序、分隔的字符串之间的差异?

例子:

String A: "a1, b4, g3, h6, t8, a0"
String B: "b4, h6, a0, t8, a1"

区别:“g3”

我无权访问此答案 Difference between two unordered deliminted lists (Oracle) 中建议的 APEX_UTIL

【问题讨论】:

    标签: string plsql delimited unordered


    【解决方案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 '/')
    

    希望对你有帮助

    【讨论】:

      【解决方案2】:

      对于这种情况,我通常更喜欢使用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;
      

      【讨论】:

        【解决方案3】:

        如果您知道它们将以逗号和/或空格分隔,那么这将起作用并且简单得多。

        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;
        

        编辑:更改为返回字符串。

        【讨论】:

        • 但这实际上并没有返回差异 - 只是如果有差异?
        猜你喜欢
        • 1970-01-01
        • 2019-04-05
        • 2015-02-18
        • 1970-01-01
        • 2012-04-27
        • 1970-01-01
        • 2013-07-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多