是否有一個簡單而優雅的方法來返回Oracle中使用PL/SQL的兩個無序分隔字符串之間的區別?PL/SQL中兩個無序分隔字符串之間的區別
例子:
String A: "a1, b4, g3, h6, t8, a0"
String B: "b4, h6, a0, t8, a1"
差異: 「G3」
我沒有訪問APEX_UTIL的建議在這個答案Difference between two unordered deliminted lists (Oracle)
是否有一個簡單而優雅的方法來返回Oracle中使用PL/SQL的兩個無序分隔字符串之間的區別?PL/SQL中兩個無序分隔字符串之間的區別
例子:
String A: "a1, b4, g3, h6, t8, a0"
String B: "b4, h6, a0, t8, a1"
差異: 「G3」
我沒有訪問APEX_UTIL的建議在這個答案Difference between two unordered deliminted lists (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;
不確定優雅,但這樣的工作:
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 '/')
希望這可以幫助
如果你知道他們將要逗號和/或空格分隔那麼這將工作,是簡單了很多。
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;
編輯:改變返回字符串。
但是,這實際上並沒有返回差異 - 只是如果有差異? – user813345
我改變了它。 – Ben
太棒了 - 謝謝! – user813345