H2数据库自定义函数在UPDATE语句中失效问题排查
字符串归一化函数在H2 SQL脚本调用中出现异常值问题
我写了一个用于字符串归一化的Java函数:
public static Object normalizeString(String source) { if (source == null) return null; String cleaned = source.replaceAll("[\\n\\r\\t]", ""); cleaned = Normalizer.normalize(cleaned, Normalizer.Form.NFD); cleaned = cleaned.replaceAll("[^\\p{ASCII}]", ""); // 移除所有非ASCII字符 cleaned = cleaned.strip(); return cleaned; }
这个函数在应用中有两处调用场景:
1. 数据库升级SQL脚本中调用
alter table entry add infostr1S VARCHAR_IGNORECASE null; CREATE ALIAS normalizeString FOR "com.zparkingb.zploger.Compute.NormalizationSupport.normalizeString"; update entry set infostr1S = normalizeString(infostr1) where infostr1 is not null;
2. AFTER INSERT和BEFORE UPDATE触发器中调用
public class TriggerUpdateEntry implements Trigger { // ... public void fire(Connection conn, Object[] oldRow, Object[] newRow) throws SQLException { if (newRow == null) { return; } // 在INSERT和UPDATE时归一化可搜索字符串 newRow[34] = NormalizationSupport.normalizeString((String) newRow[20]); // infostr1 } }
触发器调用完全正常,但SQL脚本中的UPDATE语句执行后,清理后的infostr1S列出现了类似aced0005740011523230305f4475206c6f7572642e677078的奇怪字符串。
进一步排查得到以下结论:
- 启用BEFORE UPDATE触发器时,所有值都正常;
- 删除BEFORE UPDATE触发器后,所有值都异常。
这说明问题出在SQL脚本中的自定义函数调用上。脚本的执行方式如下:
for (Path scriptPath : scripts) { try (Statement st = archive.getConnection().createStatement()) { logger.info("Executing update script " + scriptPath); st.execute("RUNSCRIPT FROM '" + scriptPath + "'"); logger.debug("Script " + scriptPath + " executed"); } catch (SQLException ex) { throw new DBException("Execution of script " + scriptPath + " failed", ex); } }
使用环境:
- H2 1.4.196(支持旧文件格式的最新版本)
- Java 11
请问这个问题是否和脚本调用方式或函数定义有关?有没有人遇到过类似的问题?
内容的提问来源于stack exchange,提问作者lvr123
相关产品推荐
相关产品推荐

