批量 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 插入,一个主记录,一个带有外键的详细记录的主要内容,如果未能解决你的问题,请参考以下文章