Обновление таблицы, объединенной по составному ключу - PullRequest
3 голосов
/ 21 марта 2012

Я пытаюсь обновить строки в таблице данных, которые пересекаются со строками в таблице меньшего индекса. Две таблицы объединены в составном PK таблицы данных, и объяснение-выбор с использованием тех же критериев показывает, что индекс используется правильно, и выбираются правильные уникальные строки, но у меня все еще есть проблемы с обновлением.

Обновление в объединенных таблицах работает нормально, когда во временной таблице есть только 1 строка, но когда у меня больше строк, я получаю MySql Error 1175 , и ни одно из указанных ГДЕ условий не распознается .

Я знаю, что могу просто отключить безопасный режим с помощью SET SQL_SAFE_UPDATES = 0, но кто-нибудь может сказать мне, что я здесь не понимаю? Почему мое условие WHERE не принимается и зачем оно вообще нужно где, когда я делаю ЕСТЕСТВЕННОЕ СОЕДИНЕНИЕ - и почему это работает только с одной строкой в ​​правой таблице (MyTempTable)?

Код

Ниже значительно упрощено, но структурно идентично создание таблицы и обновлений, представляющих мою проблему.

-- The Data Table.
Create Table MyDataTable
(
    KeyPartOne int not null,
    KeyPartTwo varchar(64) not null,
    KeyPartThree int not null,
    RelevantData varchar(200) null,
    Primary key (KeyPartOne, KeyPartTwo, KeyPartThree)
) Engine=InnoDB;

-- The 'Temp' table.
Create Table MyTempTable
(
    KeyPartOne int not null,
    KeyPartTwo varchar(64) not null,
    KeyPartThree int not null,
    Primary key (KeyPartOne, KeyPartTwo, KeyPartThree)
)Engine=Memory;

-- The Update Query (works fine with only 1 row in Temp table)
update MyDataTable natural join MyTempTable 
set RelevantData = 'Something Meaningful';

-- Specifying 'where' - roduces same effect as the other update query
update MyDataTable mdt join MyTempTable mtt
on mdt.KeyPartOne = mtt.KeyPartOne
and mdt.KeyPartTwo = mtt.KeyPartTwo
and mdt.KeyPartThree = mtt.KeyPartThree
set RelevantData = 'Something Meaningful'
where mdt.KeyPartOne = mtt.KeyPartOne
and mdt.KeyPartTwo = mtt.KeyPartTwo
and mdt.KeyPartThree = mtt.KeyPartThree;

P.S. Оба приведенных выше оператора обновления работают, как и ожидалось, когда временная таблица содержит только одну строку, но выдают ошибку при наличии более одной строки. Мне очень интересно, почему!

Ответы [ 2 ]

2 голосов
/ 21 марта 2012

В вашем первом запросе UPDATE вы используете NATURAL JOIN, что совпадает с NATURAL LEFT JOIN.

Во втором запросе UPDATE вы используете JOIN, что аналогичнокак INNER JOIN.

A LEFT JOIN - это не то же самое, что INNER JOIN, а NATURAL JOIN - это не то же самое, что JOIN.

Не уверен, что выпытаетесь это сделать, но если вы пытаетесь обновить все строки в 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'

Если это не то, что вы пытаетесьсделайте, пожалуйста, уточните, и я обновлю свой ответ.

1 голос
/ 26 марта 2012

Согласно форуму MySql, запросы на обновление действительны, и тот факт, что они не работают в Workbench с включенным режимом безопасного обновления, не означает, что с индексом что-то не так.Это просто причудливый режим Workbench «не стреляй в себя».: -)

...