打开连接上的 UCanAccess 异常 - 引用的列上不存在唯一约束

Posted

技术标签:

【中文标题】打开连接上的 UCanAccess 异常 - 引用的列上不存在唯一约束【英文标题】:UCanAccess exception on open connection - UNIQUE constraint does not exist on referenced columns 【发布时间】:2020-01-29 12:59:43 【问题描述】:

我正在尝试使用 ucanaccess 在我的 java maven 项目中创建与访问数据库 (.accdb) 的非常简单的连接。该数据库是一个外部数据库,我只需要读取一些表的内容即可完成迁移任务。我不想也不应该修改表或在数据库中写入任何内容。 我使用的java代码非常简单:

try (Connection connection = DriverManager.getConnection(databaseURL);) 
 catch (SQLException ex)  ex.printStackTrace(); 

但连接一开始就失败了,但有以下异常:

net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::5.0.0 a UNIQUE constraint does not exist on referenced columns: T1 in statement [ALTER TABLE T2 ADD CONSTRAINT "T22EB41B92-C3AB-4A64-A53C-B83095D76202" FOREIGN KEY  (C2)  REFERENCES T1 (C1) ]
    at net.ucanaccess.jdbc.UcanaccessDriver.connect(UcanaccessDriver.java:231)
    at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
    at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:251)
    at myproject.Application.main(Application.java:42)
Caused by: java.sql.SQLSyntaxErrorException: a UNIQUE constraint does not exist on referenced columns: T1 in statement [ALTER TABLE T2 ADD CONSTRAINT "T22EB41B92-C3AB-4A64-A53C-B83095D76202" FOREIGN KEY  (C2)  REFERENCES T1 (C1) ]
    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.converters.LoadJet.exec(LoadJet.java:1510)
    at net.ucanaccess.converters.LoadJet.access$000(LoadJet.java:74)
    at net.ucanaccess.converters.LoadJet$TablesLoader.loadForeignKey(LoadJet.java:695)
    at net.ucanaccess.converters.LoadJet$TablesLoader.loadTableFKs(LoadJet.java:918)
    at net.ucanaccess.converters.LoadJet$TablesLoader.recreate(LoadJet.java:807)
    at net.ucanaccess.converters.LoadJet$TablesLoader.loadTableData(LoadJet.java:877)
    at net.ucanaccess.converters.LoadJet$TablesLoader.loadTableData(LoadJet.java:871)
    at net.ucanaccess.converters.LoadJet$TablesLoader.loadTableData(LoadJet.java:837)
    at net.ucanaccess.converters.LoadJet$TablesLoader.loadTablesData(LoadJet.java:1029)
    at net.ucanaccess.converters.LoadJet$TablesLoader.loadTables(LoadJet.java:1077)
    at net.ucanaccess.converters.LoadJet$TablesLoader.access$3200(LoadJet.java:264)
    at net.ucanaccess.converters.LoadJet.loadDB(LoadJet.java:1579)
    at net.ucanaccess.jdbc.UcanaccessDriver.connect(UcanaccessDriver.java:218)
    ... 3 more
Caused by: org.hsqldb.HsqlException: a UNIQUE constraint does not exist on referenced columns: T1
    at org.hsqldb.error.Error.error(Unknown Source)
    at org.hsqldb.error.Error.error(Unknown Source)
    at org.hsqldb.TableWorks.checkCreateForeignKey(Unknown Source)
    at org.hsqldb.TableWorks.addForeignKey(Unknown Source)
    at org.hsqldb.StatementSchema.getResult(Unknown Source)
    at org.hsqldb.StatementSchema.execute(Unknown Source)
    at org.hsqldb.Session.executeCompiledStatement(Unknown Source)
    at org.hsqldb.Session.executeDirectStatement(Unknown Source)
    at org.hsqldb.Session.execute(Unknown Source)
    ... 18 more

我尝试将我的连接设置为“只读”,这样它就不会检查此约束并且不会引发异常。但我没有任何成功。

try (Connection connection = DriverManager.getConnection(databaseURL + ";readonly=true");) 
 catch (SQLException ex)  ex.printStackTrace();  

在创建连接以读取某些表时,有什么方法可以关闭此约束检查?

【问题讨论】:

根据堆栈跟踪,您似乎连接成功。但是,由于ALTER TABLE 查询而引发错误。您是否正在执行包含ALTER TABLE 查询的语句? 制作备份副本,然后在 Access 中打开数据库并对其执行“压缩和修复数据库”操作。看看有没有帮助。 @BankBuilder 我不执行任何语句。 try catch 块是我试图执行的唯一事情。这意味着,我只想打开连接。 @Gord 感谢您的建议。不幸的是,它没有帮助。 我需要一些东西来重现这个问题,请继续在 sourceforge 上打开的线程 【参考方案1】:

我无法发布用于重现问题的数据库!因为它是一个非常复杂的数据库,有很多表和关系,它不属于我。由于一般数据保护条例,我不允许分享它(即使没有数据)。

此外,我不想更改数据库中的任何内容,因此我想关闭约束检查以便能够仅连接到数据库并读取某些表的行。

最后我复制了数据库并删除了表之间的所有关系,然后代码可以连接到数据库, 但: 连接需要 30 分钟!!!!因此,即使每次我想运行我的代码(这在我的任务中实际上是不可能的)时,我都会设法从数据库中复制并删除所有表之间的所有关系,我应该等待 30 分钟只需打开一个连接!!!! 我觉得很荒谬,当某些约束不满足时,不可能关闭约束检查并打开连接以读取数据!!!

但无论如何,最后(经过两天的搜索!)我找到了适合我工作的解决方案。我不使用这种类型的 DriverManager 的任何类型的连接:

Connection connection = DriverManager.getConnection(databaseURL)

相反,我使用 DatabaseBuilder 打开我的数据库并获取表并读取行! 对于遇到同样问题并且只想连接到 MS-Access 数据库以读取一些数据而不进行任何更改的其他任何人,我建议采用这种方式。它非常简单快捷!

String fileName = "my_database.accdb";
File file = new File(fileName);
Database db = null;
DatabaseBuilder databaseBuilder = new DatabaseBuilder(file);
try 
     db = databaseBuilder.open();
 catch(IOException e) 
     e.printStackTrace();

Table myTable = db.getTable("myAccessTableName");
for(Row row : myTable) 
     String firstName = row.getString("first_name");
     String lastName = row.getString("last_name");

Database、DatabaseBuilder、Row 和 Table 来自“jackcess”。所以需要这些导入:

import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.DatabaseBuilder;
import com.healthmarketscience.jackcess.Row;
import com.healthmarketscience.jackcess.Table;

更多使用这种方式的例子可以在这里找到: Java Code Examples 和这里: UCanAccess

【讨论】:

以上是关于打开连接上的 UCanAccess 异常 - 引用的列上不存在唯一约束的主要内容,如果未能解决你的问题,请参考以下文章

如何将 UCanAccess 连接到使用数据库密码加密的 Access 数据库?

sqlserver2008R2连接数据库异常,异常内容如下

使用 iso-8859-1 在 wildfly 中打开 ucanaccess/jackcess 数据库

mysql和eclipse已经连接上但是没有创建表回出现异常吗?

实体异常:在提供程序连接上启动事务时发生错误。有关详细信息,请参阅内部异常

使用 UCanAccess 连接到数据库时出现“无效页码 1”错误