首页 > 解决方案 > 在查找子查询中引用主表以进行更新时出错

问题描述

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

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

所以,如果我做这个查询:

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'

我得到错误:

错误代码 1093。您无法在 FROM 子句中指定目标表 'BI.fact_training_event_tbl' 进行更新

我尝试执行此处推荐的操作:MySQL 错误 1093 - 无法在 FROM 子句中指定要更新的目标表,将查询嵌套在另一个中:

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 设置为 null,而不是 next_date。

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

where cc.gkey > BI.fact_training_event_tbl.gkey

或者

where cc.gkey > zz.gkey

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

关于如何解决这个问题的任何想法?

标签: mysqllookupmysql-error-1093

解决方案


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

即使您链接的解决方法看起来只是select在原始子查询周围添加了一个 -layer,例如select * from (your original subquery),您错过了它们工作的原因:它们使用派生表而不是(依赖)子查询(这就是 @Cheekysoft隐含的意思链接答案中的临时表)。派生表不能依赖于外部查询(因此根本问题消失了)。它或多或少被视为任何实际表(请注意,例如,在您的情况下,您必须命名派生表;有关此问题的更多详细信息,请参见我的aa另一个答案)。

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

因此,基本策略是将您需要的所有行放入派生表中,然后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

“在”派生表 ( base) 的“内部”,您可以做任何您想做的事情并根据需要经常使用,但是对外部fact_training_event_tbl的依赖是由- 条件在“外部”完成的。 fact_training_event_tblbaseon

由于不仅base是(派生的)表,fact_training_event_tbl也是(实际的)表,所以一般也可以这样做

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 字段,它是连续的 int 主键”字面意思(所以没有间隙),这将起作用。但即使不是,它也应该说明在这种情况下使用普通表和派生表之间的类比。


推荐阅读