UCanAccess SQL 插入失败;查询在 MS Access 意外令牌中工作正常 (UcanaccessStatement.java:222)

Posted

技术标签:

【中文标题】UCanAccess SQL 插入失败;查询在 MS Access 意外令牌中工作正常 (UcanaccessStatement.java:222)【英文标题】:UCanAccess SQL Insert failing; query works fine in MS Access unexpected token (UcanaccessStatement.java:222) 【发布时间】:2016-02-18 20:56:36 【问题描述】:

这是我第一次尝试用 Java 构建一些东西,这里的最终目标是将一个 excel 文件简单地导入到 MS Access 数据库中。

我怀疑存在某种数据不兼容错误,或者 UCA 正在执行某些操作来清理查询,但我对 Java 或 UCanAccess 了解不足,无法追踪。

这是我组装的查询,可以很好地直接在 MS Access 中插入数据:

INSERT INTO XXXX_XA_Data_1 ([Date],[Fund Ticker],[Unique ID],[Cash & Cash Equiv],[Mkt Value of Security Holdings],[Today's Future Variation Margin],[Other Net Assets],[Total Net Assets],[Fund Shares],[NAV],[Fund Sales ($)],[Fund Sales (Shares)],[Fund Redemptions ($)],[Fund Redemptions (Shares)]) 
VALUES (#12/01/2001#,"XXXXX","00000000-XXXXX",0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000);

部分数据已替换为 X 和 0,但所有列名都相同。

我已经尝试了几种变体来看看哪些方法会起作用,我可以让它插入基金代码、唯一 ID 和现金和现金等价物。基于这些尝试,我认为日期格式或某些列名破坏了它,但我找不到遇到这个确切问题的其他人。

这是java:

Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
db = DriverManager.getConnection("jdbc:ucanaccess://C:" + path_db);

...

Statement s = db.createStatement();
try 
  int result = s.executeUpdate(rowquery);
 catch (Exception e) 
  e.printStackTrace();

还有完整的踪迹:

[2016-02-18 13:37:29.053]: SQL Insert failed for item 1. Aborting with exception: net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::3.0.3.1 unexpected token: [
    at net.ucanaccess.jdbc.UcanaccessStatement.executeUpdate(UcanaccessStatement.java:222)
    at DailyImporter.main(DailyImporter.java:226)
Caused by: java.sql.SQLSyntaxErrorException: unexpected token: [
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
    at org.hsqldb.jdbc.JDBCStatement.fetchResult(Unknown Source)
    at org.hsqldb.jdbc.JDBCStatement.executeUpdate(Unknown Source)
    at net.ucanaccess.jdbc.ExecuteUpdate.executeWrapped(ExecuteUpdate.java:67)
    at net.ucanaccess.jdbc.AbstractExecute.executeBase(AbstractExecute.java:152)
    at net.ucanaccess.jdbc.ExecuteUpdate.execute(ExecuteUpdate.java:50)
    at net.ucanaccess.jdbc.UcanaccessStatement.executeUpdate(UcanaccessStatement.java:220)
    ... 1 more
Caused by: org.hsqldb.HsqlException: unexpected token: [
    at org.hsqldb.error.Error.parseError(Unknown Source)
    at org.hsqldb.ParserBase.unexpectedToken(Unknown Source)
    at org.hsqldb.ParserBase.checkIsIdentifier(Unknown Source)
    at org.hsqldb.ParserDQL.readSimpleColumnName(Unknown Source)
    at org.hsqldb.ParserDQL.readSimpleColumnNames(Unknown Source)
    at org.hsqldb.ParserDML.compileInsertStatement(Unknown Source)
    at org.hsqldb.ParserCommand.compilePart(Unknown Source)
    at org.hsqldb.ParserCommand.compileStatements(Unknown Source)
    at org.hsqldb.Session.executeDirectStatement(Unknown Source)
    at org.hsqldb.Session.execute(Unknown Source)
    ... 7 more

这里是否有需要解决的列名或其他数据格式问题?或者 UCanAccess 以外的库可以简单地在 MS Access db 上运行 SELECT/INSERT 查询?

【问题讨论】:

你能把整个脚本一起显示出来,尤其是追加查询语句,而不是单独显示吗?我怀疑values 前面有一个空间,但在你布置的时候无法分辨。并请换行以避免水平滚动。 查询是直接从控制台粘贴的——它与构建时完全一样,并在 rowquery 变量中传递。 【参考方案1】:

UCanAccess 目前难以解析字段名称包含撇号(也称为“单引号”字符)' 的 SQL 语句,例如,

sql = "INSERT INTO XXXX_XA_Data_1 ([Today's Future Variation Margin]) VALUES (1)";

该问题已报告给 UCanAccess 开发团队,预计将在 UCanAccess 的未来版本中得到修复。

同时,如果您不需要执行任何复杂的 SQL 查询,那么您可以import com.healthmarketscience.jackcess.*; 并直接使用 Jackcess API。例如,要执行与上面的 INSERT 语句等效的操作,您可以这样做

String dbFileSpec = "C:/Users/Public/example.accdb";
try (Database db = DatabaseBuilder.open(new File(dbFileSpec))) 
    Table tbl = db.getTable("XXXX_XA_Data_1");
    HashMap rowData = new HashMap();
    rowData.put("Today's Future Variation Margin", 1);
    tbl.addRowFromMap(rowData);

【讨论】:

效果很好!谢谢!剩下的唯一问题是 Access 似乎无法“识别”新数据 - 我无法使用 MSAccess 界面找到它(大多数用户会以这种方式读取数据库)。我知道是因为尝试两次运行插入会引发有关违反唯一 ID 的异常。是否有某种方法可以确保在添加行时也更新元数据? Jackcess 确实更新了所有相关的元数据,但它在不使用 Access 数据库引擎的情况下这样做,因此不会通知来自 MSACCESS.EXE 的现有连接。更多详情here. 很不幸,但我很高兴听到这不仅仅是我。感谢您的帮助。 是的,"单引号问题"发生,使用 ucanaccess,如果列名中同时有空格和单引号(如果没有空格,它可以工作)。请注意,作为一种变通方法,您可以简单地在插入语句中省略列名中的单引号,这样就可以了。

以上是关于UCanAccess SQL 插入失败;查询在 MS Access 意外令牌中工作正常 (UcanaccessStatement.java:222)的主要内容,如果未能解决你的问题,请参考以下文章

UCanAccess/Jackcess 在 Access 中创建查看/保存查询

插入时sql查询失败

在 Ucanaccess 中插入错误

ucanaccess SQL 异常:游标状态无效:已识别游标未打开

使用 UCanAccess 插入 ResultSet 时出现“必须在插入之前设置所有列”错误

如何使用 UCanAccess 插入行?