批量 MySQL 插入,一个主记录,一个带有外键的详细记录

Posted

技术标签:

【中文标题】批量 MySQL 插入,一个主记录,一个带有外键的详细记录【英文标题】:Batch MySQL inserts, one a primary record, one a detail record with foreign key 【发布时间】:2013-11-03 16:25:31 【问题描述】:

我有一个将大量数据记录到 mysql 数据库的应用程序。生产版本已经批量运行插入语句以提高性能。我们正在稍微更改 db 架构,以便将一些无关数据发送到我们可以在查找时加入的不同表。

但是,我正在尝试正确设计查询以与我们的批处理系统一起使用。我想使用 mysql LAST_QUERY_ID,所以我不必担心获取生成的密钥并匹配它们(似乎是一项非常困难的任务)。

但是,我似乎找不到将不同的插入语句添加到批处理中的方法,那么如何解决这个问题?我假设我需要构建第二批并向其中添加所有详细查询,但这意味着 LAST_QUERY_ID 失去了意义。

s = conn.prepareStatement("INSERT INTO mytable (stuff) VALUES (?)");
while (!queue.isEmpty())
    s.setLong(1, System.currentTimeMillis() / 1000L);
    // ... set other data
    s.addBatch();

    // Add insert query for extra data if needed
    if( a.getData() != null && !a.getData().isEmpty() )
        s = conn.prepareStatement("INSERT INTO mytable_details (stuff_id,morestuff)
                                   VALUES (LAST_INSERT_ID(),?)");
        s.setString(1, a.getData());
        s.addBatch();
    

【问题讨论】:

您能详细说明一下吗? “似乎找不到方法”是什么意思?上面的代码是抛出异常还是什么? 上面的代码不能工作,因为语句被覆盖了。如果有第二个查询的数据,则第一个查询永远不会运行。如果不创建第二个语句变量/批处理,我将无法使其工作,但随后查询将无序运行,并且 last_insert_id 无用 谢谢。我在下面添加了我的答案,但我不确定它是否会对你有所帮助。 【参考方案1】:

这不是批处理的工作方式。批处理仅适用于一个Statement,对于PreparedStatement,这意味着您只能为同一条语句添加批量参数。您的代码也忽略了执行语句。

对于你想做的事情,你应该使用setAutoCommit(false),执行这两个语句然后commit()(或者如果发生错误则回滚)。

另外,我建议您研究检索生成的密钥的 JDBC 标准方法,因为这会使您的代码不那么特定于 MySQL。另见Retrieving AUTO_INCREMENT Column Values through JDBC。

【讨论】:

【参考方案2】:

我现在已经修复了它,但我希望有更好的方法。我构建了一个额外数据值的数组列表,我可以将其与从批量插入返回的 generatedKeys 相关联。在第一个查询批处理执行后,我使用正确的 ids/data 构建第二个批处理。

【讨论】:

以上是关于批量 MySQL 插入,一个主记录,一个带有外键的详细记录的主要内容,如果未能解决你的问题,请参考以下文章

记录sql server 的批量删除主外键的sql语句

mysql表中,表的外键关联自身主键,为啥插入不了数据?

11.21

补12.关于mysql的外键约束

如何删除有外键的mysql记录

mysql中添加外键问题,求高手