【问题标题】:Incrementing value in table with unique key causes constraint error使用唯一键递增表中的值会导致约束错误
【发布时间】:2014-03-19 00:55:52
【问题描述】:

我创建了一个表

CREATE TABLE `tests` (`num` INTEGER UNIQUE, value VARCHAR(255))

我在其中添加了两行:

INSERT INTO `tests` VALUES(0, "a")
INSERT INTO `tests` VALUES(1, "b")

我现在的目标是插入一行 num = 0,但要做到这一点,我需要将这两行的索引向上移动。

当我执行时:

UPDATE `tests` SET `num` = `num` + 1 WHERE `num` >= 0

我得到错误:

由于约束失败而无法执行语句(19个约束失败)

我的猜测是它正在递增每一行,当它通过将第一行设置为1 来递增第一行时,已经有一行具有1num,因此失败。

在标准代码中,这将通过向后迭代集合来解决,在 Sqlite 中有没有办法做到这一点?有没有其他方法可以解决这个问题?

【问题讨论】:

标签: sql sqlite web-sql


【解决方案1】:

如果您不在原地进行更新,但在临时表的帮助下,更新将起作用:

CREATE TEMP TABLE t2 AS SELECT * FROM tests WHERE num >= 0;
DELETE FROM tests WHERE num >= 0;
INSERT INTO tests SELECT num + 1, value FROM t2;
DROP TABLE t2;

或者,使用足够大的增量,不会有冲突。 然后您必须再次执行此操作才能恢复到所需的值:

UPDATE tests SET num = num + 3     WHERE num     >= 0;
UPDATE tests SET num = num - 3 + 1 WHERE num - 3 >= 0;

【讨论】:

  • 这是其他人将来可能想要的一个很好的答案,但在我的情况下不起作用。此更新经常发生,因为它试图有一个粗略的有序列表,需要在中间进行插入操作,因此临时表是不合理的。双重更新技巧是一个巧妙的技巧,没想到这一点。我的答案是放弃约束并确保我的代码经过良好测试。
【解决方案2】:

我建议使用 IDENTITY 约束。使用此约束自动进行递增。

CREATE TABLE test
(
    ID int IDENTITY(1,1) PRIMARY KEY UNIQUE,
    value VARCHAR(255)
)

然后你可以写 INSERT INTO 测试(值)值('a') 并且您不必担心递增。

Identity (1,1) 不是必需的(如果您只写 identity,则默认为),但您可以尝试其他组合,例如 IDENTITY(int a, int b) - 然后您从 a 开始并按 b 值递增。

【讨论】:

  • 我评论说我的目标是在开头插入,因此 Identity 是不合理的,因为这会给我一个大于表中当前任何数字的数字。我需要实际更改这些值。
猜你喜欢
  • 1970-01-01
  • 2015-12-17
  • 2018-09-14
  • 2020-02-15
  • 2014-02-23
  • 1970-01-01
  • 1970-01-01
  • 2017-05-27
  • 2011-11-27
相关资源
最近更新 更多