如何在FROM子句中更新目标表?

时间:2013-08-10 14:44:25

标签: mysql sql ruby-on-rails sql-update

我准备了以下SQL语句,以便使用master_id表的相应行的staging更新id表的字段mastermaster包含按其位置唯一的对象。因此,如果有的话,应该返回最多一个id。

UPDATE staging 
SET master_id = (
  SELECT m.id 
  FROM master m, staging s
  WHERE m.lat = s.lat 
  AND m.lon = s.lon
);

然而,查询失败并显示You can't specify target table 'staging' for update in FROM clause。我该如何解决这个问题?

此外,我认为可以使用JOIN优化查询。如果你可以帮忙,那就太棒了! 这是我尝试加入两个表:

UPDATE staging s
INNER JOIN master m
ON s.lat = m.lat
AND s.lon = m.lon
SET s.master_id = m.id;

Query OK, 0 rows affected (0.38 sec)
Rows matched: 14976  Changed: 0  Warnings: 0

接下来尝试:

UPDATE staging s 
INNER JOIN (
  SELECT id, lat, lon
  FROM master
) AS m
ON s.lat = m.lat
AND s.lon = m.lon
SET s.master_id = m.id;

Query OK, 0 rows affected (0.35 sec)
Rows matched: 14976  Changed: 0  Warnings: 0

请注意,如果这会影响解决方案的语法,我会使用MySQL。


要确认实际存在匹配的行(每个< - 这是预期的),此查询应该证明这一事实。

SELECT COUNT(*)
FROM master m, staging s
WHERE t.lat = s.lat
AND t.lon = s.lon;

+----------+
| count(*) |
+----------+
|    14976 |
+----------+
1 row in set (0.05 sec)

1 个答案:

答案 0 :(得分:0)

您正在将表格中的每个master_id设置为:

  SELECT m.id 
  FROM master m, staging s
  WHERE m.lat = s.lat 
  AND m.lon = s.lon

与您的想法相反,这将返回许多行。尝试将其作为独立查询! SQL并不神奇地理解您只想要与您正在更新的行匹配lat和lon的m.id.

目前SQLFiddle已经关闭,所以我不能仔细检查,但你可能想要这样的东西:

UPDATE staging 
SET master_id = (
  SELECT m.id 
  FROM master m
  -- where m.lat,m.lon  are the lat,lon values **in the row you're updating**
  WHERE m.lat = staging.lat 
  AND m.lon = staging.lon
);

请注意,这将在分段中的每个master_id值设置为NULL,而不会找到匹配的(lat,lon)。这可能是也可能不是问题。