[英]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.