You can't specify target table 'a' for update in FROM clause


項目中有一個功能變動上線,其中有一張表ttt的字段cc,歷史數據需要處理,把字段cc中為’xxx’的值替換為'yyy'。

表A結構如下:

CREATE TABLE `ttt` (
  `id` bigint NOT NULL,
  `aa` int NOT NULL COMMENT 'xxx',
  `bb` int(11) NOT NULL COMMENT 'xxx',
  `cc` varchar(64) NOT NULL COMMENT 'xxx',
  ...
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_aa_bb_cc` (`aa`,`bb`,`cc`) USING BTREE,
) ENGINE=InnoDB DEFAULT CHARSET=utf8

更新sql如下:

UPDATE ttt SET cc='yyy' WHERE cc='xxx';

執行報錯:
Duplicate entry 'xx-xx-yyy' for key 'uk_aa_bb_cc'

因為相同的aa、bb下可能已經有cc值為'yyy'的數據了,
比如已有歷史數據:
aa bb cc
1 1 xxx
1 1 yyy
這個時候執行更新sql,就會有2條1 1 yyy,由於字段aa、bb、cc因業務屬性設置為唯一索引,所以更新失敗。

修改更新sql,將有相同yyy的數據排除掉:

UPDATE ttt a SET a.cc='yyy' WHERE a.cc='xxx' 
AND NOT EXISTS (SELECT 1 FROM ttt b WHERE a.aa=b.aa AND a.bb=b.bb AND b.cc='yyy');

執行報錯:
You can't specify target table 'a' for update in FROM clause

改成IN條件:

UPDATE ttt a SET a.cc='yyy' WHERE a.cc='xxx' 
AND NOT IN (SELECT id FROM ttt b WHERE a.aa=b.aa AND a.bb=b.bb AND b.cc='yyy');

也報同樣的錯。

這個錯誤在MySQL會出現,在SQLServer、Oracle上沒有,意思是:
不能先select出同一表中的某些值,再update這個表(在同一語句中),即不能依據某字段值做判斷再來更新某字段的值。

修改sql如下:

UPDATE ttt a SET a.cc='yyy' WHERE a.cc='xxx' 
AND a.id NOT IN (
SELECT id FROM(SELECT id FROM ttt b WHERE a.aa=b.aa AND a.bb=b.bb AND b.cc='yyy')c
);

執行還是報錯:
Unknown column 'a.aa' in 'where clause'

看來直接嵌套一層查詢也不行。
再次修改sql,使用UPDATE JOIN語法:

UPDATE ttt a
LEFT JOIN ttt b ON a.aa=b.aa AND a.bb=b.bb AND b.cc='yyy'
SET a.cc='yyy'
WHERE a.cc='xxx' AND b.id IS NULL

因為需要排除掉相同記錄,這里用LEFT JOIN並且條件為IS NULL的方式
再次執行sql成功。

在執行sql前后可以用sql進行數據查詢,比如:
查詢沒有相同aa、bb且ccc僅有'xxx'的數據(即預先驗證上面的更新sql影響的數據情況):

SELECT * 
FROM ttt a
LEFT JOIN ttt b ON a.aa=b.aa AND a.bb=b.bb AND b.cc='yyy'
WHERE a.cc='xxx' AND b.id IS NULL

查詢有相同aa、bb且cc存在xxx、yyy值的數據:

SELECT aa,bb,COUNT(*) FROM ttt
WHERE cc IN('xxx','yyy')
GROUP BY aa,bb
HAVING COUNT(*)>1

通過aa、bb條件查詢:

SELECT * FROM ttt WHERE aa='xx' AND bb='yy';

參考:
MySQL 中 You can't specify target table '表名' for update in FROM clause錯誤解決辦法
MySQL update join語句


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM