我正在尝试找到是否有一种可靠的方法(使用SQLite)来查找要插入的下一行的ID,在插入之前。我需要将id用于另一个insert语句,但是没有选择立即插入并获取下一行。
预测下一个ID就像获取最后一个ID并添加一个一样简单吗?这是保证吗?
编辑:多一点推理...... 我无法立即插入,因为插入可能最终被用户取消。用户将进行一些更改,SQL语句将被存储,用户可以从中保存(一次插入所有行)或取消(不更改任何内容)。在程序崩溃的情况下,所需的功能是没有任何改变。
答案 0 :(得分:23)
试试SELECT * FROM SQLITE_SEQUENCE WHERE name='TABLE';
。这将包含一个名为seq
的字段,该字段是所选表的最大数字。将1添加到此值以获取下一个ID。
另请参阅SQLite Autoincrement article,这是上述信息的来源。
干杯!
答案 1 :(得分:14)
一次性删除或提交一系列数据库操作正是交易的目的。在用户开始摆弄之前查询BEGIN;
,在他/她完成后查询COMMIT;
。您可以保证应用所有更改(如果您提交)或一切都被废弃(如果您查询ROLLBACK;
,程序崩溃,电源熄灭等)。一旦你从数据库中读取数据,你也可以保证在交易结束之前数据是好的,这样你就可以抓住MAX(id)
或任何你想要的东西,而不必担心竞争条件。
答案 2 :(得分:3)
在某些情况下,您可以在sqlite3_last_insert_rowid返回的值中添加1,例如,使用相同的数据库连接,并且没有其他并发编写器。当然,您可以参考sqlite源代码来备份这些假设。
但是,您可能也会认真考虑使用不需要预测下一个ID的其他方法。即使你正确使用你正在使用的sqlite版本,未来的事情也会发生变化,这肯定会使得迁移到另一个数据库变得更加困难。
答案 3 :(得分:2)
插入具有某种INVALID标志的行,获取ID,根据需要进行编辑,必要时删除或标记为有效。那并且不要担心序列中的差距
顺便说一句,你需要弄清楚如何自己做无效的部分。将某些内容标记为NULL可能会有所不同。编辑:如果可以,请使用Eevee建议使用正确的交易。这项工作要少得多。
答案 4 :(得分:2)
我意识到使用SQLite的应用程序很小,而SQLite有自己的语义。此处发布的其他解决方案可能会在此特定设置中产生您想要的效果,但在我看来,到目前为止我读过的每一个解决方案都是根本不正确的,应该避免使用。
在正常环境中,应该不惜一切代价避免持有用户输入的交易。如果需要存储中间数据,处理此问题的方法是将信息写入临时表以实现此目的,然后尝试在原子事务中写入所有信息。持有事务会在多用户环境中引发死锁和并发噩梦。
在大多数环境中,您无法假设在事务中通过SELECT检索的数据是可重复的。例如
SELECT Balance FROM Bank ...
UPDATE Bank SET Balance = valuefromselect + 1.00 WHERE ...
更新后,余额的价值可能会有所改变。有时您可以通过在事务中首先更新您对Bank感兴趣的行来解决这个问题,因为这可以保证锁定行,防止进一步更新更改其值,直到您的事务完成为止。
但是,在这种情况下,有时确保一致性的更好方法是检查有关更新的WHERE子句中数据内容的假设,并检查应用程序中的行数。在上面的示例中,当您“UPDATE Bank”时,WHERE子句应提供balance的预期当前值:
WHERE Balance = valuefromselect
如果预期的余额不再匹配WHERE条件 - UPDATE什么也不做,rowcount返回0.这告诉你有一个并发问题,你需要在别的东西没有尝试改变时再次重新运行操作你的数据同时存在。
答案 5 :(得分:2)
select max(id) from particular_table is unreliable for the reason below..
http://www.sqlite.org/autoinc.html
“只要您从不使用最大ROWID值,并且您永远不会删除具有最大ROWID的表中的条目,上面描述的正常ROWID选择算法将生成单调递增的唯一ROWID。如果您删除了行或者您曾经删除过使用最大可能的ROWID创建一行,然后在创建新行时可以重用先前删除的行中的ROWID,并且新创建的ROWID可能不是严格按升序排列。“
答案 6 :(得分:0)
我认为这是无法做到的,因为无法确定在您询问和插入之间不会插入任何内容。 (你可能可以将表锁定到插入但是Yuck)
BTW我只使用过MySQL,但我认为这不会产生任何影响)
答案 7 :(得分:0)
您很可能应该能够+1最近的ID。我会查看有序表中现有id的所有(返回一段时间)..它们是否一致,每行的ID是否比最后一行多一个?如果是这样,你可能会没事的。不过,我会在代码中留下一些解释这个假设的评论。执行锁定有助于确保在执行此操作时不会获得其他行。
答案 8 :(得分:0)
选择last_insert_rowid()值。
答案 9 :(得分:0)
本主题中需要说的大部分内容已经...... 但是,在执行此操作时要非常小心竞争条件。如果两个人同时打开你的应用程序/网页/其中一个,并且其中一个添加了一行,另一个用户将尝试插入具有相同ID的行,你会遇到很多问题。
答案 10 :(得分:0)
select max(id) from particular_table;
下一个ID将是最大ID的+1。