2012-05-11 12 views
6

Aprendiendo SQL, perdón si esto es rudimentario. Tratando de encontrar una solución de trabajo UPDATE para el siguiente código pseudoish:UPDATE Sintaxis con ORDER BY, LIMIT y Multiple Tables

UPDATE tableA 
SET tableA.col1 = '$var' 
WHERE tableA.user_id = tableB.id 
AND tableB.username = '$varName' 
ORDER BY tableA.datetime DESC LIMIT 1 

Lo anterior se parece más a SELECT sintaxis, pero la que, básicamente, tratando de actualizar un único valor de la columna en el última fila de tablaA, donde un nombre de usuario que se encuentra en tableB.username (representado por $ varName) está vinculado a su número de ID en tableB.id, que existe como id en tableA.user_id.

Afortunadamente, eso tiene sentido. Supongo que es necesario algún tipo de JOIN, pero las subconsultas parecen problemáticas para UPDATE. Entiendo que ORDER BY y LIMIT están fuera de los límites cuando hay varias tablas involucradas en ACTUALIZAR ... Pero necesito la funcionalidad. ¿Hay alguna forma de evitar esto?

Un poco confundido, gracias de antemano.

Respuesta

15

La solución es anidar ORDER BY y LIMIT en una cláusula FROM como parte de una unión. Esto permite encontrar la fila exacta que se actualizará (ta.id) primero, luego confirmar la actualización.

UPDATE tableA AS target 
    INNER JOIN (
     SELECT ta.id 
     FROM tableA AS ta 
     INNER JOIN tableB AS tb ON tb.id = ta.user_id 
     WHERE tb.username = '$varName' 
     ORDER BY ta.datetime DESC 
     LIMIT 1) AS source ON source.id = target.id 
    SET col1 = '$var'; 

Sombrero de punta a Baron Schwartz, también denominado Xaprb, por el excelente post sobre este tema exacto: http://www.xaprb.com/blog/2006/08/10/how-to-use-order-by-and-limit-on-multi-table-updates-in-mysql/

+1

+1 para responder a su propia pregunta –

+0

** Nota: ** Esto no funciona para tablas temporales - del manual: 'No puede hacer referencia a una tabla TEMPORAL más de una vez en la misma consulta. –

0

Puede utilizar sintaxis siguiente consulta:

update work_to_do as target 
    inner join (
     select w. client, work_unit 
     from work_to_do as w 
     inner join eligible_client as e on e.client = w.client 
     where processor = 0 
     order by priority desc 
     limit 10 
    ) as source on source.client = target.client 
     and source.work_unit = target.work_unit 
    set processor = @process_id; 

Esto funciona perfectamente.