在查找子查询上引用 main table 以进行更新时出错

Error referencing main table on lookup subquery for update

首先,由于有关错误 1093 的线程显示了一个简单的子查询,因此之前没有回答这个问题。在我的例子中,我正在查找引用主 table 的下一条记录。请不要在未先阅读整个问题的情况下将其标记为重复。

我需要更新日期错误(1970-01-01)的table的记录,使用下一条记录的数据(根据gkey字段,它是连续的int主键) .

所以,如果我执行此查询:

SELECT aa.gkey,
       aa.course_date,
       (select course_date from BI.fact_training_event_tbl bb where bb.gkey = (
            select min(cc.gkey) 
            from BI.fact_training_event_tbl cc 
                 where cc.gkey > aa.gkey)) as next_date
from BI.fact_training_event_tbl aa
where course_date = '1970-01-01'

它正确地带来了记录,正如预期的那样:

gkey   course_date  next_date
====   ===========  =========
4103   1970-01-01   2017-03-23
4884   1970-01-01   2017-03-22
5047   1970-01-01   2017-03-23

我现在需要用 next_date 更新 course_date 字段,但如果我尝试 运行 以下内容:

update BI.fact_training_event_tbl aa
    set course_date =
    (select course_date from BI.fact_training_event_tbl bb where bb.gkey = (
            select min(cc.gkey)
    from BI.fact_training_event_tbl cc
         where cc.gkey > BI.fact_training_event_tbl.gkey))
where course_date = '1970-01-01'

我收到错误:

Error Code 1093. You can't specify target table 'BI.fact_training_event_tbl' for update in FROM clause

我尝试按照此处的建议进行操作:MySQL Error 1093 - Can't specify target table for update in FROM clause,将查询嵌套在另一个查询中:

update BI.fact_training_event_tbl as zz
    set course_date =
    (select course_date from
    (select course_date from BI.fact_training_event_tbl as bb where bb.gkey = (
            select min(cc.gkey) 
      from BI.fact_training_event_tbl as cc
           where cc.gkey > gkey)) as aa )
where course_date = '1970-01-01'

但我得到的只是将 date_course 设置为空,而不是 next_date。

如果我尝试像这样引用主要 table:

where cc.gkey > BI.fact_training_event_tbl.gkey

where cc.gkey > zz.gkey

它说:未知列 BI.fact_training_event_tbl.gkey 或 zz.gkey。

关于如何实现这一点有什么想法吗?

1093 错误的根本原因是 MySQL 无法访问您想要第二次更新的 table,并且直接依赖于 table。

即使您链接的解决方法看起来只是在原始子查询周围添加了一个 select 层,例如select * from (your original subquery),您错过了它们工作的原因:它们使用派生的 table 而不是(依赖的)子查询(这就是 @Cheekysoft 对 隐式临时 table 的含义 在您的 linked answer). A derived table cannot depend on the outer query (so the underlying problem is gone). It is more or less treated like any actual table (notice e.g. that you have to name a derived table, in your case aa; see e.g. 中了解更多有关此的详细信息。

但这也意味着你不能在这里使用任何对外部 table 的依赖,无论你想如何欺骗 MySQL 这样做。你例如得到 unknown column-error 因为此时外部查询无法访问以供参考。

所以基本策略是将您需要的所有行放入派生 table,然后对 select 您需要更新实际行的行执行 join行:

update fact_training_event_tbl
join ( your original select that returns 3 rows ) base
on base.gkey = fact_training_event_tbl.gkey
set course_date = base.course_date

"Inside" 派生出 table (base),你可以随心所欲地使用 fact_training_event_tbl,但要依赖 fact_training_event_tbl =39=]outer fact_training_event_tblon 条件完成 base 的 "outside"。

因为不仅 base 是(派生的)table,而且 fact_training_event_tbl 也是(实际的)table,因此通常也可以

update fact_training_event_tbl
join fact_training_event_tbl base
on base.gkey = fact_training_event_tbl.gkey + 1
set course_date = base.course_date

在你的情况下,如果你的意思是 "gkey field, which is consecutive int primary key" 字面意思(因此没有间隙),这将起作用。但即使不是,它也应该说明在这种情况下使用普通 table 和派生 table 之间的类比。

报告最终有效的查询,感谢 solarflare 的解决方案:

update fact_training_event_tbl orig
join ( SELECT aa.gkey,
    aa.course_date,
    (select course_date from BI.fact_training_event_tbl bb where bb.gkey = (
            select min(cc.gkey) from BI.fact_training_event_tbl cc where cc.gkey > aa.gkey)) as next_date
from BI.fact_training_event_tbl aa
where course_date = '1970-01-01' ) base
on base.gkey = orig.gkey
set orig.course_date = base.next_date