【问题标题】:Update to table joined on composite key更新在复合键上连接的表
【发布时间】:2012-04-05 13:58:09
【问题描述】:

我正在尝试更新与较小索引表中的行相交的数据表中的行。这两个表在数据表的复合 PK 上连接,使用相同标准的解释选择表明索引使用正确,并且获取了正确的唯一行 - 但我仍然遇到更新问题。

当临时表中只有 1 行时,连接表上的更新工作正常,但是当我有更多行时,我得到 MySql Error 1175,并且我指定的 WHERE 条件均不被识别。

我知道我可以使用 SET SQL_SAFE_UPDATES=0 关闭安全模式,但谁能告诉我这里有什么我不明白的地方?为什么我的 WHERE 条件不被接受,为什么在我进行 NATURAL JOIN 时它甚至需要一个 where - 为什么这仅适用于右侧表 (MyTempTable) 中的一行?

守则

下面是大大简化的,但结构相同的创建表和更新代表我的问题。

——数据表。 创建表 MyDataTable ( KeyPartOne int 不为空, KeyPartTwo varchar(64) 不为空, KeyPartThree int 不为空, 相关数据 varchar(200) 空, 主键(KeyPartOne、KeyPartTwo、KeyPartThree) ) 引擎=InnoDB; -- 'Temp' 表。 创建表 MyTempTable ( KeyPartOne int 不为空, KeyPartTwo varchar(64) 不为空, KeyPartThree int 不为空, 主键(KeyPartOne、KeyPartTwo、KeyPartThree) )引擎=内存; -- 更新查询(在 Temp 表中只有 1 行可以正常工作) 更新 MyDataTable 自然加入 MyTempTable set RelevantData = '有意义的东西'; -- 指定 'where' - 产生与其他更新查询相同的效果 更新 MyDataTable mdt 加入 MyTempTable mtt 在 mdt.KeyPartOne = mtt.KeyPartOne 和 mdt.KeyPartTwo = mtt.KeyPartTwo 和 mdt.KeyPartThree = mtt.KeyPartThree 设置 RelevantData = '有意义的东西' 其中 mdt.KeyPartOne = mtt.KeyPartOne 和 mdt.KeyPartTwo = mtt.KeyPartTwo 和 mdt.KeyPartThree = mtt.KeyPartThree;

附:当临时表仅包含一行时,上述两个更新语句都按预期工作,但是当有多行时给我错误。我真的很好奇为什么!

【问题讨论】:

    标签: mysql join composite-key


    【解决方案1】:

    在您的第一个UPDATE 查询中,您使用NATURAL JOIN,这与NATURAL LEFT JOIN 相同。

    在您的第二个UPDATE 查询中,您使用JOIN,这与INNER JOIN 相同。

    LEFT JOININNER JOIN 不同,NATURAL JOINJOIN 不同。

    不确定您要做什么,但如果您尝试更新 MyDataTable 中 MyTempTable 中存在相应条目的所有行,则此查询应该可以解决问题:

    UPDATE
        myDataTable mdt
        INNER JOIN MyTempTable mtt ON
            mdt.KeyPartOne = mtt.KeyPartOne
            AND mdt.KeyPartTwo = mtt.KeyPartTwo
            AND mdt.KeyPartThree = mtt.KeyPartThree
    SET
        mdt.RelevantData = 'Something Meaningful'
    

    如果这不是你想要做的,请澄清,我会更新我的答案。

    【讨论】:

    • 您能否引用“NATURAL JOIN,与 NATURAL LEFT JOIN 相同”的来源?根据the man page - 向下滚动到“连接处理更改” - 自然连接与带有“USING”的equivi-join 相同,它被解释为指定字段上的内部连接。此外,我还尝试了您的建议 - 请注意,这是我在“--指定'位置'”下发布的第二个查询。它仍然抱怨在哪里缺少密钥,所以我提供了 - 但它似乎没有被识别为有效密钥。
    • @ValAkkapeddi:也许我弄错了。我查看了同一页,上面写着“两个表的自然 [LEFT] JOIN ...”并将其解释为 NATURAL JOINNATURAL LEFT JOIN 相同,但再看一遍后,我意识到可能不对。另外,我刚刚意识到我没有完全理解你的问题,问题是 MySQL 正在抛出错误,因为你处于安全更新模式。抱歉,我对安全更新模式的怪癖没有任何经验。
    • 无论如何都要尝试!只是想知道这说明了 MySql 使用复合索引的方式。希望有人能解释一下!
    • 如果你通过类似WHERE mdt.KeyPartOne LIKE '%'...这样的操作来欺骗它怎么办?
    【解决方案2】:

    根据 MySql 论坛,更新查询是有效的,并且它们在打开安全更新模式的 Workbench 中不起作用这一事实并不表明索引有任何问题。这只是 Workbench 的“不要自欺欺人”模式的一个怪癖。 :-)

    【讨论】:

      猜你喜欢
      • 2015-03-20
      • 2014-03-14
      • 1970-01-01
      • 1970-01-01
      • 2017-10-25
      • 1970-01-01
      • 1970-01-01
      • 2016-09-03
      • 1970-01-01
      相关资源
      最近更新 更多