it-swarm.com.de

MySQL-Aktualisierungsabfrage mit linkem Join

Tabellenschema

Tabellenname: file_manager_folder

Zeilen: id, parentId, name

Meine Abfrage simuliert das Verschieben eines Ordners in einen anderen Ordner und akzeptiert ein Array mit IN (?). 

Ich möchte, dass mein Update nur einen Ordner "verschiebt", wenn es nicht bereits einen Ordner mit derselben ParentId und demselben Namen gibt. Das Verhalten, das Sie unter einem normalen Dateisystem erwarten würden. 

Also zum Beispiel:

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

Wäre eine Abfrage, die nichts über die parentId und den Namen prüft ... Aber wie kann ich den linken Join zur Arbeit bringen? 

Hier ist einer, den ich ausprobiert habe ... was absolut nicht funktioniert. 

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

24
Layke

Sie möchten also nur Ordner verschieben, wenn ein Ordner mit demselben Namen unter dem übergeordneten Zielordner nicht vorhanden ist:

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);

Die Join-Bedingung sucht nach einem Ordner mit demselben Namen unter dem übergeordneten Ziel. Die WHERE-Klausel testet, dass kein solcher Ordner existiert (f2.name ist nur dann null, wenn der äußere Join keine Übereinstimmung findet).

49
Bill Karwin

Ich denke, das sollte gelöst werden, indem eine eindeutige Bedingung/index für die Spalten parentid und name verwendet wird. Andernfalls kann jeder Benutzer mit INSERT/UPDATE-Zugriff auf die Tabelle Ihre Geschäftsregel umgehen.

CREATE UNIQUE INDEX blah_uk ON FILE_MANAGER_FOLDER(parentId, name) USING BTREE
2
OMG Ponies

Naiv, aber wie wäre es damit?

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'))
2
eyescream

Wenn Sie einenNOT INanstelle vonLEFT joinverwenden, wird die Leistung beeinträchtigt.

Führen Sie Explain vor der Abfrage aus, und das Problem ist offensichtlich.

0
Sunil