Operación única de "intercambio"...
INTERCAMBIO(@pos_antiguo, @pos_nuevo)
UPDATE
my_table
SET
position = CASE WHEN position = @old_pos THEN @new_pos ELSE @old_pos END
WHERE
position IN (@old_pos, @new_pos)
Sin embargo, esto no se expande fácilmente a una tabla de operaciones de intercambio. Esto se debe a que intentará hacer todos los intercambios a la vez, cuando en realidad los intercambios deben ocurrir en un orden específico...
Además, si desea hacer SWAP(@id, @new_pos), debe realizar una subconsulta o unirse a sí mismo en la tabla que está actualizando. A MySQL no le gusta eso, y aunque hay formas de sortear la limitación, hace que las cosas se pongan un poco complicadas...
UPDATE
my_table
INNER JOIN
(SELECT position AS old_pos, @new_pos AS new_pos FROM (SELECT position FROM my_table WHERE id = @id)) AS params
ON my_table.position IN (params.old_pos, params.new_pos)
SET
myTable.position = CASE WHEN position = old_pos THEN new_pos ELSE old_pos END
(Yo creo eso funcionará)
Ambos asumen que AMBOS @old_pos y @new_pos, o @id y @new_pos se encuentran, no verifica, y lo hará hacer un lío si no existen.
Esto se puede resolver colocándolo en una transacción y retrocediendo si ROW_COUNT() muestra que solo se actualizó 1 registro.