[英]Why does this SQLite UPDATE statement write changes to all records in the table?
此查询返回 40319 条记录:
SELECT artist,
title,
composer AS alib_composer,
master.composer AS master_composer
FROM alib
INNER JOIN
master ON hex(alib.__path) = hex(master.__path) AND
alib.l_title = lower(master.title) AND
alib.composer != master.composer AND
length(alib.composer) != length(master.composer) AND
master.composer LIKE "% %" AND
alib.composer NOT LIKE "% %";
将以上转换为以下 UPDATE 查询会导致 alib 中的所有记录都被更新。 有人能帮我理解为什么会这样吗?
UPDATE alib
SET composer = (
SELECT composer
FROM master
WHERE hex(alib.__path) = hex(master.__path) AND
alib.l_title = lower(master.title) AND
alib.composer != master.composer AND
length(alib.composer) != length(master.composer) AND
master.composer LIKE "% %" AND
alib.composer NOT LIKE "% %"
);
我怀疑我知道为什么,但将更新变成这样:
UPDATE alib
SET composer = master.composer
WHERE hex(alib.__path) = hex(master.__path) AND
alib.l_title = lower(master.title) AND
alib.composer != master.composer AND
length(alib.composer) != length(master.composer) AND
master.composer LIKE "% %" AND
alib.composer NOT LIKE "% %";
导致 SQLite 抱怨:
Error while executing SQL query on database 'x': no such column: master.composer
因为外部/主 UPDATE SQL 上没有 WHERE 子句,即它基本上是
UPDATE alib SET composer = the_result_of_the_subquery;
您需要一个 WHERE 子句来说明要更新的行:-
UPDATE alib SET composer = the_result_of_the_subquery WHERE ??????;
或者使用您的代码:-
UPDATE alib
SET composer = (
SELECT composer
FROM master
WHERE hex(alib.__path) = hex(master.__path) AND
alib.l_title = lower(master.title) AND
alib.composer != master.composer AND
length(alib.composer) != length(master.composer) AND
master.composer LIKE "% %" AND
alib.composer NOT LIKE "% %"
)
WHERE the_expression_to_restrict_which_rows_are_updated
;
这尚未经过全面测试,但这可能是您正在寻找的解决方案:-
WITH cte AS
(
SELECT
master.composer AS master_composer,
alib.rowid AS arowid
FROM alib
INNER JOIN
master ON hex(alib.__path) = hex(master.__path)
AND alib.l_title = lower(master.title)
AND alib.composer != master.composer
AND length(alib.composer) != length(master.composer)
AND master.composer LIKE '% %'
AND alib.composer NOT LIKE '% %'
)
UPDATE alib
SET composer =
(
SELECT cte.master_composer FROM cte WHERE cte.arowid = alib.rowid
)
WHERE alib.rowid IN (SELECT arowid FROM cte);
以下 SQL 用于测试:-
DROP TABLE IF EXISTS alib;
DROP TABLE IF EXISTS master;
CREATE TABLE IF NOT EXISTS alib (__path,l_title,composer);
CREATE TABLE IF NOT EXISTS master (__path,title,artist,composer);
INSERT INTO alib VALUES
('path1','this','bert'),
('path2','something else','Joe'),
('path2','something else','Joe'), -- duplicate likely irrelevant but still updated
('path2','something else','Joe Someone'), -- already has space in composer skipped
('path100','an so on','x') -- no equivalent in master
;
INSERT INTO master VALUES
('path1','this','fred','bert'), -- ignored as no space
('path1','this','fred bloggs','Julia smith'),
('path2','something else','Alison','Joe Brown')
;
/* DEMO OF EXTRACTED ROWS */
WITH cte AS
(
SELECT
master.composer AS master_composer,
alib.rowid AS arowid
FROM alib
INNER JOIN
master ON hex(alib.__path) = hex(master.__path)
AND alib.l_title = lower(master.title)
AND alib.composer != master.composer
AND length(alib.composer) != length(master.composer)
AND master.composer LIKE '% %'
AND alib.composer NOT LIKE '% %'
)
SELECT * FROM cte;
WITH cte AS
(
SELECT
master.composer AS master_composer,
alib.rowid AS arowid
FROM alib
INNER JOIN
master ON hex(alib.__path) = hex(master.__path)
AND alib.l_title = lower(master.title)
AND alib.composer != master.composer
AND length(alib.composer) != length(master.composer)
AND master.composer LIKE '% %'
AND alib.composer NOT LIKE '% %'
)
UPDATE alib
SET composer =
(
SELECT cte.master_composer FROM cte WHERE cte.arowid = alib.rowid
)
WHERE alib.rowid IN (SELECT arowid FROM cte);
SELECT * FROM alib;
DROP TABLE IF EXISTS alib;
DROP TABLE IF EXISTS master;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.