我正在尝试在DELETE
语句中创建子查询以提高性能。普通DELETE
语句有效,但子查询语句要么不加选择地删除所有行,要么每次调用只删除一行。我很困惑为什么陈述不等同。
跳到"什么不起作用"看问题陈述。
我正在使用sqlite3
中的python2
来管理带有相关标签的图片数据库。
该表的架构是:
CREATE VIRTUAL TABLE "files" USING fts3(fname TEXT, orig_name TEXT, tags TEXT, md5sum TEXT);
标签被组织为逗号分隔列表,因此sqlite
中的直接字符串比较不会(轻松)起作用,因此我添加了辅助函数TAGMATCH
def tag_match(tags, m):
i = int(m in [i.strip() for i in tags.split(',')])
return i
db.create_function('TAGMATCH', 2, tag_match)
这就是我想要/期望的。它会删除列tags
包含标记'DELETE'
的所有行。根据我的理解,下行是需要对表格进行线性扫描。由于"危险"删除表中的某些内容我确实想要使用MATCH
以防万一,在某些假设的情况下,匹配会发生另一个非预期的标记,即。 'DO NOT DELETE THIS'
。
DELETE FROM files WHERE TAGMATCH(tags, 'DELETE')
为了加快速度,我尝试了另一个stackoverflow帖子中的技巧,其中MATCH
用于缩小搜索范围,然后对这些结果进行直接字符串比较,即
SELECT * FROM (SELECT * FROM table WHERE words MATCH keyword) WHERE words = keyword
我尝试在这里使用这个技巧,但它会删除表中的每一行。
DELETE FROM files WHERE TAGMATCH((
SELECT tags FROM files WHERE tags MATCH 'DELETE'), 'DELETE')
这是我第一次提出来的。我现在意识到这不是一个特别好的解决方案,但是因为它的效果让我感到很困惑,我将它包括在内。此语句仅删除包含标记'DELETE'
的一行。如果再次调用,它会删除另一行,依此类推,直到删除'DELETE'
的所有行:
DELETE FROM files WHERE rowid = (
SELECT rowid FROM (
SELECT rowid, tags FROM files WHERE tags MATCH 'DELETE')
WHERE TAGMATCH(tags, 'DELETE'))
答案 0 :(得分:2)
以下查询删除所有内容,因为WHERE
子句求值为一个数字,如果它本身评估为TRUE
:
DELETE FROM files WHERE TAGMATCH((
SELECT tags FROM files WHERE tags MATCH 'DELETE'), 'DELETE')
相当于
DELETE FROM files WHERE 1 -- or whatever ##
相反,请考虑将EXISTS
与子查询结合使用,该子查询与主查询相关:
DELETE FROM files WHERE EXISTS
(SELECT 1
FROM (SELECT rowid, tags FROM files WHERE tags MATCH 'DELETE') sub
WHERE TAGMATCH(sub.tags, 'DELETE') AND sub.rowid = files.rowid)
或者,使用您的尝试,将=
转换为IN
,因为前者仅使用找到的第一条记录。
DELETE FROM files WHERE rowid IN
(SELECT rowid
FROM (SELECT rowid, tags FROM files WHERE tags MATCH 'DELETE') sub
WHERE TAGMATCH(sub.tags, 'DELETE'))