使用UCanAccess向含计算字段的Access表插入Null值失败
表结构说明
- d1:double类型
- d2:double类型,默认值为null
- d:计算字段,公式为
IIf((If([d1] Is Null,0,[d1])=-999),Null,IIf([d2] Is Not Null,Round(([d1]+[d2])/2,1),[d1]))
问题描述
在Access客户端中向d2插入null值完全正常,但使用UCanAccess执行插入操作时,触发如下错误:
net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::4.x.x external routine invocation exception: null value not allowed
at ucanaccess@5.0.1/net.ucanaccess.jdbc.UcanaccessStatement.execute(UcanaccessStatement.java:159)
at javaapplication23.JavaApplication23.main(JavaApplication23.java:35)
使用的Java代码如下:
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver"); con = DriverManager.getConnection("jdbc:ucanaccess://" + database+ ";singleconnection=true", "", ""); try(Statement stmt = con.createStatement();){ stmt.execute("INSERT INTO Tab (d1, d2) VALUES (2.1, null);"); }
已尝试的方法:移除计算字段后操作可正常执行,但这不可行;试过用Nz()函数替代IS NULL,但计算字段不允许使用Nz函数。
问题原因
UCanAccess对Access计算字段的null值处理逻辑与Access原生客户端存在差异,在嵌套IIf的计算逻辑中,当显式插入d2为null时,UCanAccess会错误地判定某个中间步骤的null值非法,而Access原生能正确识别该场景下null的合法性。
解决方案
调整计算字段公式逻辑
重新组织计算逻辑的分支顺序,修正原公式中的If为Access标准的IIf函数,避免触发UCanAccess的null校验误判,修改后的公式:IIf(IIf([d1] Is Null, 0, [d1])=-999, Null, IIf([d2] Is Null, [d1], Round(([d1]+[d2])/2,1)))利用d2默认值,不指定字段插入
修改SQL语句,不显式插入d2的值,让其自动使用默认的null,绕过UCanAccess的校验:INSERT INTO Tab (d1) VALUES (2.1);升级UCanAccess版本
尝试将UCanAccess升级到最新稳定版,新版本可能已修复计算字段处理null值的相关bug。
内容的提问来源于stack exchange,提问作者Sophia

