2012-07-19 29 views
14

Tengo una base de datos SQLite con la tabla myTable y las columnas id, posX, posY. El número de filas cambia constantemente (puede aumentar o disminuir). Si conozco el valor de id para cada fila y el número de filas, ¿puedo realizar una única consulta SQL para actualizar todos los campos posX y posY con diferentes valores de acuerdo con la identificación?Actualizar varias filas con valores diferentes en una sola consulta SQL

ejemplo:

--------------------- 
myTable: 

id posX posY 

1  35  565 
3  89  224 
6  11  456 
14  87  475 
--------------------- 

pseudo código para la consulta SQL:

" UPDATE myTable SET posX[id] = @arrayX[id], posY[id] = @arrayY[id] " 

@arrayX, arrayY son matrices que almacenan nuevos valores para el campo posX y posY.

si, por ejemplo arrayX y arrayY contener siguientes valores:

arrayX = { 20, 30, 40, 50 } 
arrayY = { 100, 200, 300, 400 } 

la base de datos después de la consulta debería tener este aspecto:

--------------------- 
myTable: 

id posX posY 

1  20  100 
3  30  200 
6  40  300 
14  50  400 
--------------------- 

es esto posible? Estoy actualizando una fila por consulta en este momento. Pero va a tomar cientos de consultas a medida que aumenta el recuento de filas. Por cierto, estoy haciendo todo esto en AIR.

+0

Tal vez esto puede ayuda http://dba.stackexchange.com/questions/17590/find-last-max-value-according-to-timestamp-using-update-method – adopilot

Respuesta

18

Hay un par de maneras de lograr esto decentemente de manera eficiente.

Primero -
Si es posible, puede hacer algún tipo de inserción masiva en una tabla temporal. Esto depende en cierta medida de su RDBMS/lenguaje de host, pero en el peor de los casos esto se puede lograr con un SQL dinámico simple (usando una cláusula VALUES()), y luego una actualización estándar desde otra tabla. La mayoría de los sistemas proporcionan utilidades para carga a granel, aunque

Segundo -
Y esto es algo dependiente de RDBMS, así, se podría construir una instrucción de actualización dinámica.En este caso, cuando la cláusula VALUES(...) dentro del CTE se ha creado en la marcha:

WITH Tmp(id, px, py) AS (VALUES(id1, newsPosX1, newPosY1), 
           (id2, newsPosX2, newPosY2), 
           ......................... , 
           (idN, newsPosXN, newPosYN)) 

UPDATE TableToUpdate SET posX = (SELECT px 
           FROM Tmp 
           WHERE TableToUpdate.id = Tmp.id), 
         posY = (SELECT py 
           FROM Tmp 
           WHERE TableToUpdate.id = Tmp.id) 


WHERE id IN (SELECT id 
      FROM Tmp) 

(De acuerdo con la documentación, esta debe ser válida la sintaxis SQLite, pero no puedo conseguir que se trabajo en un violín)

+0

gracias, creo que daré una oportunidad a las declaraciones dinámicas. – astralmaster

+0

¿Podría poner su código en la respuesta misma? En este momento si ese enlace muere, su respuesta se convierte en inútil. –

+0

@GeorgeStocker - ah, gracias. De alguna manera me perdí la etiqueta original, y mi declaración de ejemplo no era válida en el RDBMS objetivo. Con suerte, ahora funcionaría ... –

4

Algo como esto podría funcionar para usted:

"UPDATE myTable SET ... ; 
UPDATE myTable SET ... ; 
UPDATE myTable SET ... ; 
UPDATE myTable SET ... ;" 

Si alguno de los valores de Posy posX o son los mismos, entonces ellos podrían combinarse en una sola consulta

UPDATE myTable SET posX='39' WHERE id IN('2','3','40'); 
+0

puedes preparar declaraciones como esta en un editor de texto y pégalos directamente en la línea de comando. funciona bien si no tiene demasiadas actualizaciones para hacer. – pavitran

14

Sí, se puede Haga esto, pero dudo que mejore las actuaciones, a menos que su consulta tenga una latencia realmente grande.

que podría hacer:

UPDATE table SET posX=CASE 
     WHEN id=id[1] THEN posX[1] 
     WHEN id=id[2] THEN posX[2] 
     ... 
     ELSE posX END, posY = CASE ... END 
WHERE id IN (id[1], id[2], id[3]...); 

El costo total se da más o menos por: NUM_QUERIES * (COST_QUERY_SETUP + COST_QUERY_PERFORMANCE). De esta manera, derribas un poco en NUM_QUERIES, pero COST_QUERY_PERFORMANCE aumenta enormemente. Si COST_QUERY_SETUP es realmente grande (por ejemplo, está llamando a un servicio de red que es muy lento), entonces, sí, puede que termine en la cima.

De lo contrario, trataría de indexar en la identificación, o modificar la arquitectura.

En MySQL creo que podría hacer esto más fácilmente con un INSERT múltiple en la actualización de clave duplicada (pero no estoy seguro, nunca intenté).

+0

buen ejemplo! desafortunadamente, como dije, el número de filas va a cambiar, por lo tanto, el número de operadores "CUÁNDO" necesitaría ser alterado constantemente. – astralmaster

+0

Si está realmente interesado en hacer esto, puede compilar la consulta dinámicamente. La consulta se divide en cinco o seis piezas que se vuelven a ensamblar, tres de ellas (primer y segundo CASE y la cláusula IN) creadas dentro de un único bucle WHILE. Deberías hacer algo como esto de todos modos, si los valores cambian ... – LSerni

+0

Más o menos en lo que estaba pensando. Gracias. – astralmaster

-9

Pruebe con "juego de la tableta al día (fila = 'valor' donde id = 0001 '), (fila =' valor2' donde id = 0002'), ...

+1

Esto no funciona. –

+0

¡¿Qué es esto ?! – Mafujul

Cuestiones relacionadas