【问题标题】:Efficient way to update one-to-many relationship table on an SQLite database在 SQLite 数据库上更新一对多关系表的有效方法
【发布时间】:2022-01-06 13:51:33
【问题描述】:

我有一个 SQLite 数据库,其中包含两个具有一对多关系的表,如下所示:

People
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`name` VARCHAR(200) NOT NULL,
`unique_identifier` VARCHAR(200)

Address
`id` VARCHAR(20) PRIMARY KEY AUTOINCREMENT,
`people_id` INTEGER,
`includes_unique_indentifier` VARCHAR(256),
`name` VARCHAR(200) NOT NULL,
FOREIGN KEY(people_id) REFERENCES People(id)

Address 表中有一些记录的people_idnull。对于这些地址,他们属于哪个人,可以通过匹配People.unique_identifierAddress.includes_unique_identifier 的正则表达式来识别。

忽略数据冗余,我想更新每个Address.name 以匹配其对应的People.name 记录。

目前我的查询如下所示:

UPDATE address
SET name = (
  SELECT notes
  FROM people
  WHERE address.people_id = id OR address.includes_unique_indentifier LIKE ("%" || unique_identifier || "%")
)

据我了解,这是一个低效的查询,因为它会查看 Address 表并递归地为表中的每条记录运行子查询。我正在寻找一种有效执行此更新的方法。我使用的 SQLite 版本不支持 UPDATE 查询中的 FROM 子句。

目前,Address 表上不存在索引。

【问题讨论】:

  • 您的 SQLite 版本没有其他方法。您必须使用相关子查询,问题是运算符 LIKE 很可能不会使用索引,即使它存在。你也可以试试运营商 GLOB:address.includes_unique_indentifier GLOB ("*" || unique_identifier || "*")
  • @forpas 感谢您的澄清。我认为 LIKEGLOB 运算符是相同的,除了后者使用 Unix 正则表达式匹配但在这两种情况下,如果我是正确的,则不会使用索引。那么这个查询与我的查询相比有什么优势呢?另外为了扩展您的评论,假设我确实升级到了更高版本的 SQLite,那么查询是什么来提高效率?
  • LIKE 和 GLOB 相似但不相同。我建议将 GLOB 作为测试的替代方案。对于使用 UPDATE...FROM 语法的查询,请检查我的答案。
  • 将您标记为答案,尽管答案是我最初使用的查询,只是发现我使用的 SQLite 版本不支持它。所以无论如何,除非我升级,否则似乎没有一个好的解决方案。谢谢!

标签: sql sqlite join sql-update sql-like


【解决方案1】:

如果您计划升级到支持 UPDATE ... FROM ... 语法 (3.30.0+) 的版本,您可以使用此查询来模拟表的连接:

UPDATE address AS a
SET name = p.name
FROM people AS p
WHERE p.id = a.people_id OR a.includes_unique_indentifier LIKE '%' || p.unique_identifier || '%';

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 1970-01-01
    • 2018-09-26
    • 2017-05-30
    相关资源
    最近更新 更多