PL/SQLを使用してOracleで2つの順序付けられていない区切り文字列の違いを返す簡単でエレガントな方法はありますか?
例:
String A: "a1, b4, g3, h6, t8, a0"
String B: "b4, h6, a0, t8, a1"
違い:「g3」
この回答で提案されているように、APEX_UTILにアクセスできません2つの順序付けられていない区切りリストの違い(Oracle)
PL/SQLを使用してOracleで2つの順序付けられていない区切り文字列の違いを返す簡単でエレガントな方法はありますか?
例:
String A: "a1, b4, g3, h6, t8, a0"
String B: "b4, h6, a0, t8, a1"
違い:「g3」
この回答で提案されているように、APEX_UTILにアクセスできません2つの順序付けられていない区切りリストの違い(Oracle)
私は通常、このような状況では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;
それらがコンマおよび/またはスペースで区切られることがわかっている場合、これは機能し、はるかに簡単です。
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;
編集:文字列を返すように変更します。