Java JDBC PreparedStatement 外键约束失败

Posted

技术标签:

【中文标题】Java JDBC PreparedStatement 外键约束失败【英文标题】:Java JDBC PreparedStatement Foreign Key Constraint Failed 【发布时间】:2015-05-14 16:07:48 【问题描述】:

我正在使用 SQLite 和 JDBC 设计一个计费程序,并且我正在尝试使用这个辅助方法:

public static void preparedInsert(String query, String[] inserters) 
    Connection c = connect();
    try 
        PreparedStatement statement = c.prepareStatement(query);

        for (int i = 0; i < inserters.length; i++) 
            statement.setObject(i + 1, "\'" + inserters[i] + "\'");
        
        statement.executeUpdate();
        c.commit();
        JOptionPane.showMessageDialog(null, "Database updated!");

     catch (SQLException e) 
        JOptionPane.showMessageDialog(null, "Error updating database: " + e.getMessage());
    
    disconnect(c);


public static Connection connect() 
    Connection c = null;
    try 
        Class.forName("org.sqlite.JDBC");
        SQLiteConfig config = new SQLiteConfig();  
        config.enforceForeignKeys(true);  
        c = DriverManager.getConnection("jdbc:sqlite:MRWBilling.db", config.toProperties());
        c.setAutoCommit(false);
     catch ( Exception e ) 
        JOptionPane.showMessageDialog(null, "Error connecting to database: " + e.getMessage());
    
    return c;


public static void disconnect(Connection c) 
    try 
        c.close();
     catch (SQLException e) 
        JOptionPane.showMessageDialog(null, "Error disconnecting from database: " + e.getMessage());
    

我要传入的参数是这样的:

SQLiteJDBC.preparedInsert("insert into timesheets(date, attorney, notes) values(?, ?, ?);", 
            new String[]date, attorneyName, notes);   

Timesheets 有四行:id、日期、律师和注释,其中 id 设置为自动递增,其中律师是律师表的外键。我传入的律师名实际上存在于律师表中。

当我使用常规语句时,这在之前的构建中运行良好,但现在我已经切换到准备好的语句,我得到了这个:

Error updating database: [SQLITE_CONSTRAINT] Abort due to constraint violation (FOREIGN KEY constraint failed)

我不知道自己做错了什么。有什么建议么?

【问题讨论】:

【参考方案1】:

包裹参数的附加单引号可能导致 FK 违规。在你的循环中使用它:

statement.setString(i+1, inserters[i]);

您可能还需要从insert 语句中删除分号。

【讨论】:

我不敢相信这很重要?但它确实 - 谢谢,伙计。我想我觉得有点傻——这件事快把我逼疯了。 是的,那是因为您试图插入一个值带引号(例如'Matlock' 而不是Matlock)。很高兴听到它起作用了!【参考方案2】:

李,

您可以尝试像下面那样在最后删除分号吗 “插入时间表(日期,律师,笔记)值(?,?,?)”

【讨论】:

感谢您的回复。我删除了分号,没有发生任何不同。我觉得它是可选的? 它是可选的,但有时非标准的 jdbc 驱动程序无法解析带有分号的 SQL。【参考方案3】:

还要验证律师姓名是否与律师表中的完全相同,有时我们会忘记区分大小写

【讨论】:

再次感谢。是的,完全一样。当我使用常规语句而不是准备好的语句时,所有这些都有效。【参考方案4】:

您的preparedInsert 方法似乎造成了问题。尝试像下面这样改变它

PreparedStatement 语句 = c.prepareStatement(query);

    for (int i = 0; i < inserters.length; i++) 
        statement.setString(i + 1, inserters[i]);
    

【讨论】:

谢谢——这与 Mick 上面提供的解决方案相同。感谢您的帮助。

以上是关于Java JDBC PreparedStatement 外键约束失败的主要内容,如果未能解决你的问题,请参考以下文章

JDBC-PreparedStatement实现CURD(笔记)

java连接SQL Server数据库

DBeaver客户端工具结果集缓存实现的猜测

SQLHelper--java类

SQL DATE 与 java.sql.Date 中的时区

Java_JDBC连接数据库