跟踪 SQL 中的新主键

Posted

技术标签:

【中文标题】跟踪 SQL 中的新主键【英文标题】:Keeping track of new primary keys in SQL 【发布时间】:2011-12-05 11:50:50 【问题描述】:

抱歉,这是一个很长的问题,但它涉及数据库的一般问题:

我正在使用 sqlite/jdbc(在这种情况下),并且我正在尝试跟踪在向表中添加行时创建的自动 ID。该数据库有一个主表“Person”和称为“training”和“induction”的其他表。这个想法是人名和其他基本细节进入“人”表,一个人很多人有很多“培训”和“入职”。因此,我可以通过 SELECT * FROM INDUCTIONS WHERE PERSON_ID = 不管来查找给定人员的所有归纳。

问题在于创建数据库时,我必须添加一个人,然后跟踪他们获得的 AUTOINCREMENTing ID,然后在另一个表中使用该 ID 作为外键创建条目:

所以

int id = 0;    
PreparedStatement prepPerson = conn.prepareStatement("insert into persons values (?, ?);");
prepPerson.setString(2, p.getName());
prepPerson.addBatch();

然后

PreparedStatement prepInductions = conn.prepareStatement("insert into inductions values (?, ?, ?, ?);");

Then loop over all the inductions 
prepInductions.setInt(2, id);
prepInductions.setString(3, i.getSite());
prepInductions.setString(4, i.getExpiryDate());
prepInductions.addBatch();

我希望与数据库的交互是“原子的”,所以我想做

prepPerson.executeBatch();
prepInductions.executeBatch();
id++;

我意识到可以改为添加人员,执行 getGeneratedKeys(),然后使用新人员的正确 row_id 添加归纳,但我不希望在添加人员之后但在归纳之前发生异常。如果发生这种情况,那么我将不得不回滚时间并删除此人。

目前我知道我每次都从外部源重新创建数据库,我使用本地整数变量跟踪 row_id,我知道这很危险。

这种情况没有通用的解决方案吗?还是我非常担心与数据库的“原子”交互?

【问题讨论】:

请澄清一下为什么好的旧交易不适合您。 AFAIK sqlite 支持它们并且 setAutocommit(false) 将隐式启动一个新事务。 【参考方案1】:

请使用getGeneratedKeys() 检索生成的 ID。

要保持数据完整性,请使用事务。通常,JDBC 使用“autoCommit”模式,但在这种情况下,您需要手动处理事务。

在您的连接上调用.setAutoCommit(false) 并使用.commit().rollback() 提交或放弃更改。

(查看ConnectionJavadoc)。

【讨论】:

你的意思是rollback()而不是abort()(后者是为了强行关闭连接)? 感谢大家的快速回复。它现在点击自动提交的内容。根据示例,我在执行批次之前将其设置为 false 并在它们之后将其设置为 true ,但没​​有确切地意识到原因 - 我根本没有 .commit(),但它仍然有效。所以你可以这么几个.executeBatch()es,然后一个.commit(),一旦你完成了?这正是我需要的。解决了。​​ @Mike 在处于活动事务中的连接上调用 autoCommit(true) 将调用 commit()(如 javadoc 中所述)。 @马克。是的,这似乎工作得很好。 (另外,刚刚学会了关闭()结果集的缓慢方法。)再次感谢大家。【参考方案2】:

对于这样的场景,一般框架是......

Begin A Transaction

 Create your primary entry
 Collect the auto-generated key
 Create your child entries

Commit The Transaction

然后,如果任何步骤失败,您可以Rollback the Transaction

在 SQLite 中,我相信 last_insert_rowid() 可用于在您第一次插入后获取自动生成的 id。

【讨论】:

【参考方案3】:

您可以使用上面提供的代码,但请确保关闭自动提交。然后,一旦加载了该人的所有归纳,您就需要手动提交事务。或者遇到错误就回滚。

这是完全原子的。

【讨论】:

以上是关于跟踪 SQL 中的新主键的主要内容,如果未能解决你的问题,请参考以下文章

如何为特定的新主键记录插入默认值记录?

可跟踪实体主键违规 EF 4 问题

具有新主键的重复记录 (VBA)

无法将 Quickblox Sdk 2.4 指向或配置到 android 应用程序中的新(跟踪)实例

SQL,两张表,一张共享主键

Ajax 应用程序中的 Facebook 转化跟踪像素