在查询子查询上引用主表进行更新时出错,

时间:2018-10-27 14:13:09

标签: mysql lookup mysql-error-1093

首先,由于有关错误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 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设置为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。

关于如何实现此目标的任何想法?

2 个答案:

答案 0 :(得分:2)

1093错误的根本原因是MySQL无法直接访问要更新的表,而该表又直接依赖该表。

即使您链接的变通方法看起来像它们只是在原始子查询周围添加了select层,例如select * from (your original subquery),您错过了它们起作用的原因:它们使用派生表而不是(相关的)子查询(@Cheekysoft在您的{{3}中使用隐式临时表的意思是}。派生表不能依赖于外部查询(因此根本的问题消失了)。它或多或少像任何实际表一样对待(注意,例如,在您的情况下,{em>您必须命名一个aa;有关例如以下内容的更多详细信息,请参见linked answer这个)。

但这也意味着您不能在这里使用对外部表的任何依赖关系,无论您想如何诱使MySQL这样做。你是出现 unknown column 错误,因为此时外部查询无法访问以供参考。

因此,基本策略是将您将需要的所有行放入派生表中,然后执行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,但是要依赖外部 { {1}通过fact_training_event_tbl条件在base的“外部”完成。

由于不仅on是(派生的)表,而且base也是(实际)表,所以通常也可以这样做

fact_training_event_tbl

在您的情况下,如果按字面意思是“ gkey字段,它是连续的int主键” (因此没有空格),则此方法有效。但是,即使没有,它也应该说明在这种情况下使用普通表和派生表的类比。

答案 1 :(得分:0)

报告最后一个有效的查询,感谢 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