SQLite,根据联合子查询的结果插入或忽略

Posted

技术标签:

【中文标题】SQLite,根据联合子查询的结果插入或忽略【英文标题】:SQLite, insert or ignore based on result of a union subquery 【发布时间】:2021-03-14 19:04:49 【问题描述】:
INSERT INTO table (field1, field2, field3, field4) VALUES (@field1, @field2, @field3, @field4) 
WHERE NOT EXISTS 
(
     SELECT 1 FROM table WHERE field1 = @field1 AND field2 = @field2
     UNION
     SELECT 1 FROM table WHERE field1 = @field2 AND field2 = @field1
);

上面的代码不起作用。

当我在数据库中有条目时:

'黑色''''吃''草'

我尝试插入新条目,例如:

'羊' '黑色' '吃''草'

或者像这样的条目:

'黑色' '羊'' '吃' '西瓜'

我不想让任何东西进入数据库。

【问题讨论】:

【参考方案1】:

如果您想要 WHERE 子句,则必须使用 INSERT ... SELECT。 你也可以通过避免UNION来简化WHERE子句:

INSERT INTO table (field1, field2, field3, field4) 
SELECT @field1, @field2, @field3, @field4 
WHERE NOT EXISTS (
  SELECT 1 FROM table 
  WHERE (field1, field2) = (@field1, @field2) 
     OR (field1, field2) = (@field2, @field1)
)

如果您的 SQLite 版本是 3.31.0+,最好创建 GENERATED 列,您可以在其基础上设置 UNIQUE 约束:

CREATE TABLE tablename(
  field1 text, 
  field2 text, 
  field3 text, 
  field4 text,
  un_min text GENERATED ALWAYS AS (MIN(field1, field2)),
  un_max text GENERATED ALWAYS AS (MAX(field1, field2)),
  UNIQUE(un_min, un_max)
);

现在您可以使用 INSERT OR IGNORE 插入新行:

INSERT OR IGNORE INTO table (field1, field2, field3, field4) VALUES (@field1, @field2, @field3, @field4);

不幸的是,SQLite 不允许向现有表添加约束。 您必须重新创建表(您可以在此处找到有关如何执行此操作的说明:ALTER TABLE 或此处:SQLite ALTER TABLE)

【讨论】:

非常感谢!事实证明,这相当缓慢。我想我应该为此创建一个唯一索引,例如有black+sheep+sheep+black 转成md5什么的 你的 SQLite 版本是多少? 1.0.113。用这种方式插入 30k 条记录大约需要一分钟 @NickFarsi 不,这不是 SQLite 的版本。执行SELECT sqlite_version()。如果它是 3.31.0,那么有一个解决方案可以生成列来创建唯一约束。 @NickFarsi 查看我编辑的答案。如果可以重新创建表,最好使用唯一约束。

以上是关于SQLite,根据联合子查询的结果插入或忽略的主要内容,如果未能解决你的问题,请参考以下文章

Sqlite:在子查询“消除”结果中排序

MySQL 数据库聚合查询和联合查询操作

MySQL的查询,子查询,联结查询,联合查询

Sqlite:如果结果为空,则为最大子查询设置默认值

MySQL 数据库聚合查询和联合查询操作

子查询事务