如何在 SQLite 中使用序列?
我正在编写一个基于 PHP 的 Web 应用程序,该应用程序应该与多个数据库系统一起使用。最重要的是 MySQL 和 SQLite,但 PostgreSQL 和其他也不错。为此,我尝试尽可能使用可移植的 SQL。如果这是不可能的,我在查询中定义了一些元词,这些元词由我的数据库层处理并转换为特定于平台的 SQL 命令。
我现在正在尝试添加序列支持。每个 DBMS 处理序列的方式都不同,没有通用的方法用 SQL 编写它们。我已经阅读并理解了 PostgreSQL 的做法。我发现了一个有趣的 MySQL 解决方案它使用 MyISAM 表来逃避事务的隔离约束。毕竟,序列不会随着它们所使用的事务而回滚,而这正是我想要的。序列应该是多用户安全的。
现在我还没有找到SQLite的解决方案。它缺乏内置的序列支持。它不提供在正在运行的事务之外存储数据的方法。我当前的实现是将表锁定得足够远以执行 SELECT MAX(...) 并使用该值。但我想完全摆脱它。在 SQLite 中,这种方法需要锁定整个数据库!
有人知道 SQLite 的解决方案吗?
I'm writing a PHP-based web application that should work with multiple database systems. The most important are MySQL and SQLite but PostgreSQL and others would also be nice. For this I try to use as portable SQL as possible. Where this isn't possible, I have defined some meta words in my queries that are handled by my DB layer and converted to platform-specific SQL commands.
I'm now trying to add sequences support. Every DBMS handles sequences differently, there is no common way to write them in SQL. I have read and understood the way PostgreSQL does it. I have found an interesting solution for MySQL that uses MyISAM tables to escape the isolation constraints of a transaction. After all, sequences are not rolled back with the transaction they're used in and that's exactly what I want. Sequences are supposed to be multi-user safe.
Now I haven't found a solution for SQLite. It lacks built-in sequence support. It doesn't provide ways to store data outside a running transaction. My current implementation is to lock the table far enough to do a SELECT MAX(...) and use that value. But I want to get rid of that entirely. In SQLite, this approach requires locking the whole database!
Does anybody know a solution for this with SQLite?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
只需创建一个常规计数器表即可。创建序列
foo
时,执行 do然后,当请求下一个计数器值时,执行 do
虽然事务中止时会回滚,但它是多用户安全的:没有两个用户会提交相同的号码。 sqlite 使用数据库锁实现并发,因此第二个写入器无论如何都会阻塞(不仅仅是因为序列更新,还因为它想要进行的其他更改)。
Just create a regular counter table. On creation of a sequence
foo
, doThen, when asking for the next counter value, do
While this gets rolled back when the transaction is aborted, it is multi-user safe: no two users will commit the same number. sqlite implements concurrency with a database lock, so the second writer will block anyway (not just because of the sequence update, but also because of the other changes it wants to make).
我会使用lastInsertRowID。这将返回最后插入数据的 rowid(等于该行的 INTEGER PRIMARY KEY 值)。
那么你就不需要任何序列了。
I would use lastInsertRowID. This returns the rowid of the last inserted data (which equals the INTEGER PRIMARY KEY value of that row).
You won't need any sequence then.
您可以模拟一个序列,首先创建一个具有自动递增主键列的表。
将所需序列数插入该表 n 次。如果您担心性能,那么您可以一次缓存 100 个序列。
如果您的序列表变得太大(这是一个很好的问题),您可以轻松获取最大 id,并删除小于它的所有内容。
You can emulate a sequence, first create one table with an auto-incremented primary key column.
Insert into that table n number of times for the number of sequences you want. If you're worried about performance, then you can cache 100 sequences at a time.
If your sequence table becomes too large - which is a nice problem to have - you can easily get the max id, and delete everything less than it.