为什么这个MySQL更新不起作用?

时间:2012-01-04 15:57:52

标签: mysql

有一个名为meterreadings的表格。我需要将属性meterreading从一行复制到另一行。

以下是数据样本:

 id   |  meterreadingdate  |  meterreading  |  meterreadingtype_id | created
-------------------------------------------------------------------------------
 1    |  2011-10-01        |  0             |  1                   | 2011-10-15
 2    |  2011-10-01        |  500           |  2                   | 2011-10-15

基本上,我想根据meterreading列复制所有meterreadingtype_id值,以便将meterreadingtype_id值2复制到1。

完成后数据应如下所示:

 id   |  meterreadingdate  |  meterreading  |  meterreadingtype_id | created
-------------------------------------------------------------------------------
 1    |  2011-10-01        |  500           |  1                   | 2011-10-15
 2    |  2011-10-01        |  500           |  2                   | 2011-10-15

注意我复制了500,因为meterreadingtype_id是1,我从下一行开始,因为它是2。

以下是我正在使用的查询:

update meterreadings mr1
set meterreading = 
(
    select
        meterreading 
    from meterreadings
    where
        meterreadingtype_id = 2
        and meterreadingdate = mr1.meterreadingdate
        and location_id = mr1.location_id
        and created = mr1.created
        and asset_id = mr1.asset_id
)
where asset_id in (select id from assets where model_id in (select id from models where make_id IN (81, 82)))
and meterreadingtype_id = 1

如果有帮助,我们正在使用MySQL 5和InnoDB表。

1 个答案:

答案 0 :(得分:1)

查询失败,因为您无法修改表并从子查询中的同一个表中进行选择。

请参阅Subquery Syntax

  

一个限制是子查询的外部语句必须是以下之一:SELECT,INSERT,UPDATE,DELETE,SET或DO。另一个限制是,目前您无法修改表并从子查询中的同一个表中进行选择。这适用于DELETE,INSERT,REPLACE,UPDATE等语句(因为子查询可以在SET子句中使用)LOAD DATA INFILE。

我认为你可以用一些JOIN技巧解决这个问题:

UPDATE meterreadings AS tgt
INNER JOIN (
  SELECT * FROM meterreadings
  WHERE meterreadingtype_id = 2
  ) AS src
ON tgt.meterreadingdate = src.meterreadingdate
   AND tgt.location_id = src.location_id
   AND tgt.created = src.created
   AND tgt.asset_id = src.asset_id
SET tgt.meterreading = src.meterreading

我不是MySQL专家,但我相信这是有效的,因为MySQL首先处理子查询并将结果作为临时表存储在内存中,在UPDATE期间不会更改。这样做的一个副作用是,如果子查询的结果很大,那么你就会嚼掉大量(或耗尽)内存。

解决内存问题的唯一方法(据我所知)是使用与更新目标没有直接关系的条件来削减子查询。例如,如果您要在夜间进程中执行这些更新,请使内部SELECT仅返回在过去~24小时内创建的行。