将CONFLICT子句适应新的唯一索引吗?

问题描述 投票:0回答:1

我想向现有表添加额外的唯一约束。 This和其他答案说使用sqlite是不可能的,并建议创建一个唯一索引:

ALTER TABLE example ADD COLUMN new_unique TEXT;
CREATE UNIQUE INDEX new_unique_index ON example(new_unique);

这似乎有效。但是,我在使用UPSERT时遇到了麻烦:

INSERT INTO example (foo, old_unique, new_unique) VALUES ('foo', 'old', 'new') ON CONFLICT(old_unique, new_unique) DO UPDATE SET foo='foo';

这将导致错误:

ON CONFLICT cause does not match any PRIMARY KEY or UNIQUE constraint

有什么方法可以使上述语句的ON CONFLICT子句适应新的“约束”?

我尝试使用new_unique_index,但无济于事。如果不可能,那么除了用新的唯一约束创建新表并将新表中的值复制到新表(对于新约束列为NULL)之外,还有其他选择吗?这将是沉重的。我想我可以用旧的唯一列之外的所有列创建一个新表,再加上新的唯一列,并以某种方式链接它们,但这听起来很杂乱,我不知道该如何进行。

最小可复制示例:

CREATE TABLE example (foo TEXT, old_unique TEXT, UNIQUE(old_unique));
ALTER TABLE example ADD COLUMN new_unique TEXT;
CREATE UNIQUE INDEX new_unique_index ON example(new_unique);
INSERT INTO example (foo, old_unique, new_unique) VALUES ('foo', 'old', 'new') ON CONFLICT(old_unique, new_unique) DO UPDATE SET foo='foo';
sqlite
1个回答
1
投票

有什么方法可以使上述语句的ON CONFLICT子句适应新的“约束”?

(old_unique,new_unique)不可能成为约束目标,因为没有索引将两个列组合在一起,每个索引都是一个单独的约束(所以您可以使用一个或另一个,因为我的理解是,您只能使用一个约束UPSERT子句和单个冲突目标)。

如果不是:-

CREATE UNIQUE INDEX new_unique_index ON example(new_unique);

您使用过

CREATE UNIQUE INDEX new_unique_index ON example(old_unique,new_unique);

然后以下将起作用:-

INSERT INTO example (foo,old_unique,new_unique) VALUES('foo','old','new') ON CONFLICT (old_unique,new_unique) DO UPDATE SET foo = 'foo'; 

(至少由于没有覆盖给定冲突目标的主键或索引,因此至少不被拒绝。

如果不可能,除了使用新的唯一约束创建新表并将新表中的值复制到新表之外,对于新的约束列,是否有其他方法?这将是burdensome

[例如,您可以使用:-

CREATE TABLE IF NOT EXISTS temp_example (foo, old_unique,new_unique, UNIQUE(old_unique,new_unique));
INSERT INTO temp_example SELECT *,null FROM example;
ALTER TABLE example RENAME TO old_example;
ALTER TABLE temp_example RENAME TO example;
DROP TABLE If EXISTS old_example;
  • 即当您添加一列时,它将是最后一列,则无需编码列名。