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

ffvjumwh  于 2022-12-13  发布在  Mysql
关注(0)|答案(2)|浏览(562)

首先,这个问题之前没有回答,因为关于错误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

我现在需要用下一个日期更新课程日期字段,但是如果我尝试运行以下命令:

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\u training\u event\u 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'

但我得到的只是将课程日期设置为空,而不是下一个日期。
如果我尝试这样引用主表:

where cc.gkey > BI.fact_training_event_tbl.gkey

where cc.gkey > zz.gkey

上面写着:未知栏bi.fact\u training\u event\u tbl.gkey或zz.gkey。
有什么办法让我成功吗?

polkgigr

polkgigr1#

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

ou6hu8tu2#

其根本原因是 1093 错误是mysql无法访问您想要第二次更新的表,并且对该表有任何直接依赖关系。
即使你链接的解决方法看起来只是添加了一个 select -围绕原始子查询的层,例如。 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_tbl 在“外部”完成 baseon -条件。
因为不仅 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主键”(因此没有空格),那么这将起作用。但即使不是,它也应该说明在这种情况下使用正规表和派生表之间的相似性。

相关问题