暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

mysql之You can’t specify target table for update in FROM clause错误

320

You cannot update a table and select directly from the same table in a subquery.

mysql官方文档中有这句话,我们不能在一个语句中先在子查询中从某张表查出一些值,再update这张表。

比如:

mysql> UPDATE items
SET
  retail = retail * 0.9
WHERE
  id IN (
    SELECT
      id
    FROM
      items
    WHERE
      retail / wholesale >= 1.3
      AND quantity > 100
  );


复制

这个语句执行的时候会报错:ERROR 1093 (HY000): You can't specify target table 'items' for update in FROM clause

针对这种报错,有两种方法解决:多表更新和中间表

方法一 多表更新

我们可以通过多表更新来解决这个问题,连表时一张表是实际要更新的表,另一张表是原来的子查询派生出来的表,我们使用别名引用派生表。比如上面的例子中的sql,可以改写成如下写法:

update items,
(
  SELECT
    id
  FROM
    items
  WHERE
    retail / wholesale >= 1.3
    AND quantity > 100
) a
set
  retail = items.retail * 0.9
where
  items.id = a.id

复制

方法二 中间表

中间表的含义是将子查询再包一层,比如上面的语句可以改写成:

UPDATE items
SET
  retail = retail * 0.9
WHERE
  id IN (
    select
      id
    from
      (
        SELECT
          id
        FROM
          items
        WHERE
          retail / wholesale >= 1.3
          AND quantity > 100
      ) aa
  );

复制

需要注意的是,mysql优化器可能会优化子查询,这时候可能仍然会抛出错误。我们可以使用optimizer_switch变量关闭这种行为;

#将derived_merge标志设置为off
SET optimizer_switch='derived_merge=off';


复制

derived_merge是MySQL中的查询优化技术之一,用于控制派生表合并(derived merge)优化的行为。在MySQL中,当执行复杂的查询时,可能会涉及到派生表,即在查询中使用子查询作为临时表。派生表合并是一种优化技术,它尝试将多个派生表合并为一个更简单的查询结构,以提高查询性能。

参考:https://fanyi.youdao.com/index.html#/ https://dev.mysql.com/doc/refman/8.0/en/update.html


点个“赞 or 在看” 你最好看!

喜欢,就关注我吧!

👇👇👇 谢谢各位老板啦!!!

文章转载自PostgreSQL运维技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论