MySQL存储过程改写字查询后报1093错误及性能问题咨询
错误原因分析
MySQL的1093错误是内置的核心限制:不允许在UPDATE/DELETE等写操作中,直接在FROM子句里查询当前正在操作的目标表。你重写后的版本中,ELSE分支的DELETE语句要操作subcat表(别名sx),同时WHERE条件里的子查询又直接读取同一张subcat表,就触发了这个限制。
修复方案
你可以先把需要的cat_id提前查询存入局部变量,后续逻辑直接复用这个变量即可,既绕开1093限制,也不需要修改原有业务逻辑:
DELIMITER // CREATE PROCEDURE temp ( IN `valsubcat` INT ) BEGIN DECLARE tcount INT; DECLARE valcat INT; -- 新增局部变量存储查询到的cat_id -- 提前查好cat_id,仅执行一次查询 SELECT sw.cat_id INTO valcat FROM subcat sw WHERE sw.sub_id = valsubcat LIMIT 1; SELECT COUNT(*) INTO tcount FROM subcat sz WHERE sz.cat_id = valcat; CASE WHEN tcount > 1 THEN DELETE sy FROM subcat sy WHERE sy.sub_id = valsubcat; ELSE DELETE sx, c FROM subcat sx, cat_name c WHERE sx.sub_id = valsubcat AND c.cat_id = valcat; END CASE; END // DELIMITER ; CALL temp(14);
补充说明:如果subcat表的sub_id是唯一主键或者有唯一索引,加
LIMIT 1可以进一步提升查询效率,避免不必要的全表扫描。
性能问题解答
- 你原本写的有语法错误的第二版存储过程性能确实会下降:同一个
sub_id = valsubcat的查询重复执行了3次,每次子查询都有额外开销,要是subcat表数据量大、sub_id没有索引的话,执行速度会慢很多。 - 改成上述修复版本后,性能和你最初的第一版存储过程几乎没有差异:仅多了一次主键/索引查询,开销可以忽略不计,业务逻辑也和原来完全一致。
内容的提问来源于stack exchange,提问作者Gurgen
相关产品推荐
相关产品推荐

