有一個表示地區的表,表結構與數據大概以下表。html
ID | NAME | PARENT_ID |
1 | 中國 | |
2 | 廣東省 | 1 |
3 | 廣州市 | 2 |
4 | 荔灣區 | 3 |
5 | 越秀區 | 3 |
6 | 番禺區 | 3 |
7 | 小谷圍街道 | 6 |
現爲了查詢方便,須要加一列PARENT_NAME,用以表示上級地區的名稱(雖然不符合第三範式,傳遞依賴,但有時爲了業務上的可行性、便利性,能夠按實際狀況考慮)mysql
ID | NAME | PARENT_ID | PARENT_NAME |
1 | 中國 | ||
2 | 廣東省 | 1 | |
3 | 廣州市 | 2 | |
4 | 荔灣區 | 3 | |
5 | 越秀區 | 3 | |
6 | 番禺區 | 3 | |
7 | 小谷圍街道 | 6 |
附,表的DDL、DML:sql
-- ---------------------------- -- Table structure for `t_area` -- ---------------------------- CREATE TABLE `t_area` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(256) DEFAULT NULL, `parent_id` int(11) DEFAULT NULL, `parent_name` varchar(256) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of t_area -- ---------------------------- INSERT INTO `t_area` VALUES ('1', '中國', null, null); INSERT INTO `t_area` VALUES ('2', '廣東省', '1', null); INSERT INTO `t_area` VALUES ('3', '廣州市', '2', null); INSERT INTO `t_area` VALUES ('4', '荔灣區', '3', null); INSERT INTO `t_area` VALUES ('5', '越秀區', '3', null); INSERT INTO `t_area` VALUES ('6', '番禺區', '3', null); INSERT INTO `t_area` VALUES ('7', '小谷圍街道', '6', null);
這時,須要根據已有信息,更新PARENT_NAME的數據,就有了以下的SQL:ide
/* [Err] 1093 - You can't specify target table 't' for update in FROM clause */ update t_area t set t.parent_name = (select t2.name from t_area t2 where t.parent_id = t2.id);
報出「1093 - You can't specify target table 't' for update in FROM clause」的異常。意思,意思大約爲,你不能指定更新的目標表在FROM子句中(英文很差,即便認識各個單詞,串起來就不行了。。。)性能
就如文檔所述「Currently, you cannot update a table and select from the same table in a subquery.」,見http://dev.mysql.com/doc/refman/5.5/en/update.html。spa
不知道MySQL爲何不容許這樣操做,猜,多是擔憂更新的表與查詢的表爲同一表會存在嵌套遞歸?仍是擔憂效率的問題呢?code
若是,將該表在嵌套一層,即「(select * from t_area) st」這樣得出一個臨時的結果集,即無報錯,但,這性能較差,僅僅適合較小的數據量的。(見此討論帖:http://stackoverflow.com/questions/17742214/you-cant-specify-target-table-name-for-update-in-from-clause)。htm
修改後以下:blog
--ok update t_area t set t.parent_name = (select t2.name from (select * from t_area) t2 where t.parent_id = t2.id);
具體針對這個需求,更簡單的方式,貌似也能夠:遞歸
update t_area t, t_area t2 set t.parent_name = t2.name where t.parent_id = t2.id;