我正在尝试为一个大型代码库设置一个单元测试环境。对于这些单元测试,我使用H2数据库而不是IBM DB2数据库,后者在生产中使用,并且我已经实现了一些UDF来将IBM DB2相关函数Map到H2数据库。关于项目的更多详细信息:
- Java 8 JDK 321 64位
- db2 12,数据序列号12015
- H2版本2.1.212,其中〈模式=DB2;默认空排序=高;
我正在尝试实现IBM Db2函数:strip()Reference Doc - IBM。此函数作为包含以下子句的更大select语句的一部分调用:STRIP(T2.ITEM_TYPE_NAME_GER,B,' ')。虽然我可以将第一个和最后一个输入参数Map到一个Java函数,并在H2中将此函数作为ALIAS调用,但我无法将第二个参数以正确的方式解释为String或Expression。JDBC/H2引擎总是尝试将其Map到一个表列:
org.h2.jdbc.JdbcSQLSyntaxErrorException: Feld "B" nicht gefunden
Column "B" not found; SQL statement:
SELECT T1.ITEM_TYPE_KEY,T1.SUPER_ITM_TYPE_KEY,T2.ITM_TYPE_KEY_TRANS,T2.ITEM_TYPE_NAME,T2.COMPLEX_FLAG,T2.ITEM_CATEGORY,T2.HEADER_FLAG,T2.HEADER_NO ,T2.LEVEL_NO,strip(T2.ITEM_TYPE_NAME_GER, B, ' ') ,T2.LEVEL1_DISPLAY FROM public.AA752T T1, public.AA743T T2 WHERE T1.ITEM_TYPE_KEY NOT IN ('F4CO', 'F4CB', 'F4RB', 'F4SO', 'F4SB', 'F4RO') AND T1.ITEM_TYPE_KEY = T2.ITEM_TYPE_KEY ORDER BY T2.HEADER_NO,T2.HEADER_FLAG DESC,T2.LEVEL_NO,T1.SUPER_ITM_TYPE_KEY,T2.LEVEL_PRIORITY [42122-212]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:502)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:477)
at org.h2.message.DbException.get(DbException.java:223)
at org.h2.message.DbException.get(DbException.java:199)
at org.h2.expression.ExpressionColumn.getColumnException(ExpressionColumn.java:244)
at org.h2.expression.ExpressionColumn.optimizeOther(ExpressionColumn.java:226)
at org.h2.expression.ExpressionColumn.optimize(ExpressionColumn.java:213)
at org.h2.expression.function.JavaFunction.optimize(JavaFunction.java:59)
at org.h2.command.query.Select.prepareExpressions(Select.java:1170)
at org.h2.command.query.Query.prepare(Query.java:218)
at org.h2.command.Parser.prepareCommand(Parser.java:574)
at org.h2.engine.SessionLocal.prepareLocal(SessionLocal.java:631)
at org.h2.engine.SessionLocal.prepareCommand(SessionLocal.java:554)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1116)
at org.h2.jdbc.JdbcPreparedStatement.(JdbcPreparedStatement.java:92)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:288)
at com.db.cib.gbd.gps.pbs.pricing.StaticItemDetails.retriveItemDisplayDetails(StaticItemDetails.java:920)
这是我的Java UDF:
public static String strip(String s, Expression loc, String trimConstant) {
if (loc.toLowerCase() == "b" || loc.toLowerCase() == "both") {
s = s.replaceAll("^[" + trimConstant + "]+|[ \t]+$", "");
} else if (loc.toLowerCase() == "l" || loc.toLowerCase() == "leading") {
s = s.replaceAll("^[" + trimConstant + "]+", "");
} else if (loc.toLowerCase() == "t" || loc.toLowerCase() == "trailing") {
s = s.replaceAll("[" + trimConstant + "]+$", "");
}
return s;
}
是否有可能以正确的方式获得列的Map,或者您是否可以建议一个可用作UDF别名的SQL函数(如何使用?)或解决此错误的方法?要避免此问题:我无法更改现有的sql语句。我必须为此函数找到别名。
1条答案
按热度按时间xqkwcwgp1#
在H2中不可能创建带有特殊参数的用户定义函数,在所有或几乎所有其他数据库系统中也是如此。用户定义函数只接受普通的逗号分隔的参数,参数中包含文字或表达式。
(You也不能将参数声明为
org.h2.expression.Expression
。)此处正确的解决方案是使用SQL标准中的
TRIM
函数:https://h2database.com/html/functions.html#trim
https://www.ibm.com/docs/en/db2-for-zos/11?topic=functions-trim
请注意,首字母缩略词
B
、L
和T
是DB2特定的扩展,在H2中只能使用标准的BOTH
、LEADING
和TRAILING
。如果你不能改变你的查询,你只能修改H2的源代码,并编译它自己的版本,支持
STRIP
。但实际上你可能会立即遇到一些其他的问题。当你想一次使用多个数据库系统时,你需要意识到它们彼此之间有很大的不同。H2为其他系统提供了兼容模式。但即使在这些模式中,兼容性也非常有限,这意味着您需要避免使用供应商特定的函数和其他语法元素,并且在某些情况下,可能需要为不同的系统使用不同的SQL。您还可以尝试创建具有某些值的常量
B
、BOTH
、L
、LEADING
、T
和TRAILING
并创建一个具有三个参数的函数,第二个参数的类型将是
int
(或者其他,如果您决定选择其他数据类型的值)。但是常量的名称可能会与列名冲突,因此这种解决方法远非完美,在某些查询中可能根本不起作用。