如果“性能非常重要”,则应避免子字符串上的“循环”。
这里是使用 XOR 的替代方法(由 @EvilTeach 提出)。
with string_transform as (
select 'abc def hijk www' str1, 'abc def iosk www' str2 from dual
),
str as (
select
str1, str2,
-- add suffix to handle nulls and identical strings
-- calculate XOR
utl_raw.bit_xor(utl_raw.cast_to_raw(str1||'X'),utl_raw.cast_to_raw(str2||'Y')) str1_xor_str2
from string_transform
), str2 as (
select
str1, str2,
str1_xor_str2,
-- replace all non-identical characters (not 00) with 2D = '-'
utl_raw.translate(str1_xor_str2,
utl_raw.translate(str1_xor_str2,'00','01'),
utl_raw.copies('2D',length(str1_xor_str2))) xor1
from str
), str3 as (
select
str1, str2,
-- replace all identical characters (00) with 2B (= '+') and cast back to string
utl_raw.cast_to_varchar2(utl_raw.translate(xor1,'00','2B')) diff
-- diff = ++++++++---+++++ (+ means identical position; - difference)
from str2
)
select str1, str2,
-- remove the appended suffix character
substr(diff,1,length(diff)-1) diff,
-- calculate the length of the identical prefix
instr(diff,'-')-1 same_prf_length
from str3
;
基本上这两个字符串都首先转换为 RAW 格式。 XOR 将相同的字节(字符)设置为 00。使用 translate 时,相同的字节将转换为“+”,所有其他字节都转换为“-”。
相同的前缀长度是字符串中第一个“-”的位置减一。
从技术上讲,一个(不同的)后缀字符被添加到两个字符串中以处理 NULL 和相同的字符串。
注意,如果字符串长于2000,则必须添加一些额外的处理
由于 UTL_RAW.CAST_TO_VARCHAR2 的限制。