MySQL无LEVENSHTEIN函数,需自建但受log_bin_trust_function_creators限制;SOUNDEX仅适用于英文名且忽略非字母字符;PostgreSQL推荐用fuzzystrmatch扩展直接调用levenshtein等函数。

MySQL里没有LEVENSHTEIN函数,别硬写
MySQL原生不支持LEVENSHTEIN,直接调用会报错FUNCTION does not exist。想用就得自己建函数,但要注意:MySQL 8.0+ 默认禁用自定义函数加载(log_bin_trust_function_creators=OFF),不改这个配置,CREATE FUNCTION会失败。
实操建议:
- 先确认权限和配置:
SELECT @@log_bin_trust_function_creators;,如果是0,需由DBA执行SET GLOBAL log_bin_trust_function_creators = 1; - 自定义函数性能较差,字符串超20字符时明显变慢,不适合大表
JOIN或WHERE中高频调用 - 更稳妥的替代是把相似度计算移到应用层(Python/Go),数据库只做等值或前缀匹配
SOUNDEX只适合英文名拼写纠错
SOUNDEX把字符串转成4字符的语音编码(如SOUNDEX('Smith') → 'S530'),但它对中文、数字、符号完全无效,且对英文也仅覆盖基础发音规则——'Robert'和'Rupert'结果一样,但'Tom'和'Tim'就不同。
常见错误现象:
- 拿
SOUNDEX比对手机号、邮箱、地址字段,结果全是'0000'或误匹配 - 在WHERE里写
SOUNDEX(col1) = SOUNDEX(col2),本意是模糊查重,实际漏掉大量近音但编码不同的组合(比如带空格/撇号的名字) - 没意识到
SOUNDEX自动忽略非字母字符,'O'Neil'和'ONeil'结果相同,但'O'Neall'就变成另一个编码
PostgreSQL直接用fuzzystrmatch扩展
PostgreSQL用户最省事:装上fuzzystrmatch扩展后,levenshtein()、difference()(即SOUNDEX差值)、metaphone()全都有,不用自己实现。
使用前必须先启用:
- 执行
CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;(需要superuser或database owner权限) -
levenshtein('kitten', 'sitting')返回3,支持设置最大距离阈值(第三个参数),超限直接返回-1,能显著提速 - 注意字符集:如果字段是
bytea或含多字节字符,确保数据库编码为UTF8,否则levenshtein按字节算而非字符,中文会出错
相似度数值本身没意义,得结合业务定阈值
不管是levenshtein返回的编辑距离,还是difference()返回的0–4整数,单独看都没法判断“是否相似”。关键在你的场景要什么:
- 查重人名:
levenshtein(a,b) 可能合理;但两个长地址对比,编辑距离5可能只是邮编差一位 - 想归一化到0–1范围?别用
1 - levenshtein(a,b)/GREATEST(LENGTH(a),LENGTH(b)),长度差异大会严重偏斜——'a'和'abcde'相似度算出来是0.8,显然不对 - 真正稳定的方案是:先用
LENGTH过滤长度差超20%的对,再用levenshtein,最后按业务经验卡阈值,比如“姓名相似且长度差≤1才报警”
字符串相似度不是开箱即用的开关,它是把双刃剑:阈值设松了噪音爆炸,设紧了漏掉真问题。动手前先拿100条真实样本跑一遍分布,比查文档重要得多。










