MYSQL執行如下語句報錯:
UPDATE sc SET grade =grade*1.05 WHERE grade < (SELECT AVG(grade) AS avg_grade FROM sc)
報錯信息如下:
錯誤代碼: 1093
You can't specify target table 'sc' for update in FROM clause
意思是不能在同一語句中更新select出的同一張表元組的屬性值
解決方法:將select出的結果通過中間表再select一遍即可。
UPDATE sc SET grade =grade*1.05 WHERE grade < (SELECT avg_grade FROM (SELECT AVG(grade) AS avg_grade FROM sc) AS temp)
MYSQL手冊sql-syntax.html里是這么寫的:
Incorrectly used table in subquery:
Error 1093 (ER_UPDATE_TABLE_USED) SQLSTATE = HY000 Message = "You can't specify target table 'x' for update in FROM clause"
This error occurs in cases such as the following, which attempts to modify a table and select from the same table in the subquery:
UPDATE t1 SET column2 = (SELECT MAX(column1) FROM t1);
You can use a subquery for assignment within an UPDATE
statement because subqueries are legal in UPDATE
andDELETE
statements as well as in SELECT
statements. However, you cannot use the same table (in this case, tablet1
) for both the subquery FROM
clause and the update target.
In MySQL, you cannot modify a table and select from the same table in a subquery. This applies to statements such as DELETE
, INSERT
, REPLACE
, UPDATE
, and (because subqueries can be used in the SET
clause) LOAD DATA INFILE
.
MYSQL手冊restrictions.html#subquery-restrictions里給出了限制規則和解決方法:
In general, you cannot modify a table and select from the same table in a subquery. For example, this limitation applies to statements of the following forms:
DELETE FROM t WHERE ... (SELECT ... FROM t ...); UPDATE t ... WHERE col = (SELECT ... FROM t ...); {INSERT|REPLACE} INTO t (SELECT ... FROM t ...);
Exception: The preceding prohibition does not apply if you are using a subquery for the modified table in the FROM
clause. Example:
UPDATE t ... WHERE col = (SELECT * FROM (SELECT ... FROM t...) AS _t ...);
Here the result from the subquery in the FROM
clause is stored as a temporary table, so the relevant rows in t
have already been selected by the time the update to t
takes place.
其實想想也是這樣的,對同一張表查的同時更新會引起數據不一致的問題吧,但是將查詢結果事先放到臨時表中就不會有這個問題了。