MySQL Update Query с использованием левого соединения - PullRequest
24 голосов
/ 14 июля 2010

Схема таблицы

Название таблицы: file_manager_folder

Строки: id, parentId, name

Мой запрос имитирует перемещение папки в другую папку и принимает массив с помощью IN (?).

Я хочу, чтобы мое обновление только «перемещало» папку, если папка с таким же родительским идентификатором и именем уже не существует. Такое поведение вы ожидаете при любой нормальной файловой системе.

Так, например:

UPDATE file_manager_folder set parentId = 54 where id IN( '1','2',3') 

Был бы запрос, который не проверял бы ничего о parentId и имени ... Но как я могу заставить работать левое соединение.

Вот тот, который я попробовал ... который полностью не работает.

SELECT * FROM 
    file_manager_folders as a
LEFT JOIN file_manager_folders as b on a.id = b.id 
WHERE b.id IS NOT NULL and a.id IN("1","2","3") and a.parentId = 54

UPDATE table1 LEFT JOIN table2 SET t1.x = t2.y ON condition WHERE conditions

Ответы [ 4 ]

50 голосов
/ 14 июля 2010

Таким образом, вы хотите перемещать папки, только если папка с тем же именем в целевой родительской папке не существует:

UPDATE file_manager_folder f1
LEFT OUTER JOIN file_manager_folder f2 
    ON f1.name = f2.name AND f2.parentId = 54
SET f1.parentId = 54 
WHERE f2.name IS NULL AND f1.id IN (1,2,3);

Условие соединения ищет папку с тем же именем под целевым родителем. Предложение WHERE проверяет, что такой папки не существует (f2.name имеет значение null, только если внешнее соединение не находит совпадений).

2 голосов
/ 14 июля 2010

Я думаю, что это должно быть решено с использованием уникального ограничения / индекса для столбцов parentid и name. В противном случае любой пользователь с доступом INSERT / UPDATE к таблице может обойти ваше бизнес-правило.

CREATE UNIQUE INDEX blah_uk ON FILE_MANAGER_FOLDER(parentId, name) USING BTREE
2 голосов
/ 14 июля 2010

Наивно, но как насчет этого?

UPDATE file_manager_folder SET parentId = 54 
WHERE id IN( '1','2','3') 
AND parentId != 54 
AND name NOT IN (SELECT name FROM file_manager_folder WHERE id IN ('1', '2', '3'))
0 голосов
/ 13 января 2017

Если вы используете NOT IN вместо LEFT join, которые ухудшают вашу производительность.

Запустите Explain перед запросом, и проблема очевидна.

...