1. 复现错误
今天在工作时,接到一个新需求,就是将app_page_button
表中的label_code
字段修改为edit
,条件如下:
-
只更新值为
null
的label_code
-
且以
/edit/${id}'
结尾的option_value
首先使用如下sql
查询满足上述条件的记录,如下代码所示:
SELECT
id, label, label_code, option_value
FROM
app_page_button
WHERE
label_code IS NULL
AND option_value LIKE '%/edit/${id}';
+-----+-------+------------+-----------------------+
| id | label | label_code | option_value |
+-----+-------+------------+-----------------------+
| 706 | 编辑 | NULL | put:common/edit/${id} |
| 710 | 编辑 | NULL | put:common/edit/${id} |
| 714 | 编辑 | NULL | put:common/edit/${id} |
+-----+-------+------------+-----------------------+
得到满足上述条件的记录有3条
,使用如下SQL
语句修改:
UPDATE app_page_button
SET label_code = 'edit'
WHERE
id IN (
SELECT
id
FROM
app_page_button
WHERE
label_code IS NULL AND option_value LIKE '%/edit/${id}'
);
ERROR 1093 (HY000): You can't specify target table 'app_page_button' for update in FROM clause
即You can't specify target table 'app_page_button' for update in FROM clause
的错误。
2. 分析错误
最近申请的文心一言刚审核通过,可以借助它来分析我的错误,如下图所示:
文心一言的回答,和我的本意不一致。我本想在查询结果中,更新label_code
值。
因而,我需要自己分析,来解决这个错误。
You can't specify target table 'app_page_button' for update in FROM clause
的含义:不能在同一表(app_page_button
)中查询的数据,作为同一表(app_page_button
)的更新数据。
3. 解决错误
既然不能先select
出同一表中的某些值,再update
这个表(在同一语句中),那就采用将查询结果存储到临时表(tmp
)表中,id
从这个临时表(tmp
)中获取,如下代码所示:
UPDATE app_page_button
SET label_code = 'edit'
WHERE
id IN (
SELECT id
FROM (
SELECT
id
FROM
app_page_button
WHERE
label_code IS NULL AND option_value LIKE '%/edit/${id}'
) as tmp
);
Query OK, 3 rows affected (0.01 sec)
Rows matched: 3 Changed: 3 Warnings: 0
根据Query OK, 3 rows affected (0.01 sec)
这句话可知,已更新成功,从如下SQL可以看到:
select
id, label, label_code, option_value
from
app_page_button
where
id in (706,710,714);
+-----+-------+------------+-----------------------+
| id | label | label_code | option_value |
+-----+-------+------------+-----------------------+
| 706 | 编辑 | edit | put:common/edit/${id} |
| 710 | 编辑 | edit | put:common/edit/${id} |
| 714 | 编辑 | edit | put:common/edit/${id} |
+-----+-------+------------+-----------------------+
3 rows in set (0.00 sec)