2

我正在尝试修复有关 SQL 的错误(在 Android 中使用),该语句基本上如下所示:

INSERT INTO log (time, message) VALUES (datetime('now'),<a_message>);

"datetime(now)" 似乎是数据库的关键,问题是它可以在一毫秒内调用 2 次。如果发生这种情况,将引发 SQL 错误,因为键不是唯一的。

我可以使用 REPLACE 进入,但这会覆盖一个(或多个)条目。我也可以检查错误代码,睡一会儿再试一次。我只是想知道是否有人对这个问题有更好的解决方案?我对 SQL 不是很有经验。

谢谢。

4

2 回答 2

4

无论如何,由于时区、闰秒以及许多其他会让您感到惊讶的事情的狂野和毛茸茸的世界,您应该更加犹豫是否将日期时间用作主键。绝对不能保证a1 = datetime('now')总是小于或等于下一次调用a2 = datetime('now')

阅读这篇文章,大约在他开始谈论日期、时间和时区的 1/3 处。这应该让你相信你不应该尝试做你在这个问题中要求的事情:

https://msmvps.com/blogs/jon_skeet/archive/2009/11/02/omg-ponies-aka-humanity-epic-fail.aspx

如果我想要一个快速而肮脏的 hack 解决方法,我会将插入放入一个 while 循环并在插入失败时捕获错误,然后在 1 毫秒后重试。这很糟糕,就像在卧室里弄得一团糟,但有时这是必要的,因为重新设计表以拥有一个合理的主键会花费太长时间。

但是,如果您这样做,请准备好让代码处于该 while 循环中,耐心地尝试并等待数十毫秒,当它最终找到一个开放的插槽时,它并没有达到您的预期,因为它出现了在将来发生的另一个条目之前(实际上是过去)。想到这我就头疼。

于 2012-10-15T13:23:52.387 回答
2

简单的。您不使用时间值作为主键。而是使用一个自动递增的额外列(代理键)创建表。

CREATE TABLE log (
  id         INTEGER PRIMARY KEY AUTOINCREMENT,
  time       REAL,
  message    TEXT
)

然后,您现有的 INSERT 应该可以正常工作。

如果您需要根据时间字段优化记录检索,您仍然可以这样做;只需为该字段添加索引。请注意,如果您在该字段上使用联接,则具有特定时间并不等于单个特定记录。

于 2012-10-15T13:24:12.527 回答