2012-06-13 14 views
55

En algunos casos, ejecutar una instrucción UPDATE en producción puede salvar el día. Sin embargo, una actualización borked puede ser peor que el problema inicial.¿Cómo probar una instrucción SQL Update antes de ejecutarla?

Si no se usa una base de datos de prueba, ¿qué opciones hay para decir qué hará una declaración de actualización antes de ejecutarla?

Respuesta

24

Además de usar una transacción como ha dicho Imad (que de todos modos debería ser obligatoria), también puede comprobar con cordura qué filas se ven afectadas ejecutando una selección utilizando la misma cláusula WHERE que la ACTUALIZACIÓN.

Así que si usted actualización es

UPDATE foo 
    SET bar = 42 
WHERE col1 = 1 
    AND col2 = 'foobar'; 

A continuación se le mostrará qué filas serán actualizados:

SELECT * 
FROM foo 
WHERE col1 = 1 
    AND col2 = 'foobar'; 
+1

El uso de transacciones es mejor para verificar los datos a continuación. Suponiendo que quiere verificar el resultado, concluyo que su afirmación es más compleja que una 'barra SET = 42', por lo que dentro de su sesión podrá hacer varias consultas para probar el conjunto de datos resultante ... –

+1

@ImadMoqaddem: Estoy de acuerdo y es por eso que escribí "* Además de usar una transacción como dijo Imad *" –

+0

Y si tienes 'FOREIGN KEY UPDATE CASCADE' tu sql falla – Green

40

confirmación automática OFF ...

MySQL

set autocommit=0; 

Se establece el autommit fuera para la sesión actual.

Ejecuta su resumen, compruebe qué ha cambiado y, a continuación, retráigalo si está equivocado o confirme si es lo que esperaba.

EDITAR: El beneficio de usar transacciones en lugar de ejecutar una consulta de selección es que puede verificar el conjunto resultante más fácilmente.

+7

Simplemente compruebe que su tabla admite transacciones ... –

+4

@dystroy: cada DBMS sensible admite transacciones. –

+3

Simplemente recuerde comprometer o revertir la transacción rápidamente, o corre el riesgo de bloquear otras transacciones, y en el peor de los casos, detener su aplicación. No es una buena idea ejecutar la consulta, luego almorzar, luego volver para ver los resultados. :-) –

1

Ejecute la consulta de selección en la misma tabla con todas las condiciones where que está aplicando en la consulta de actualización.

0

hacer una SELECT de ella,

como si tienes

UPDATE users SET id=0 WHERE name='jan'

convertirlo en

SELECT * FROM users WHERE name='jan'

3
No

una respuesta directa, pero he visto muchas situaciones de datos prod borked que podrían haber sido evitadas por escribiendo el WHERE cláusula primera! A veces, un WHERE 1 = 0 puede ayudar a establecer una declaración de trabajo juntos de forma segura también. Y mirar un plan de ejecución estimado, que estimará las filas afectadas, puede ser útil. Más allá de eso, en una transacción que revierte como han dicho otros.

+1

¿Qué pasa con 'WHERE FALSE'? – SystemParadox

+0

@SystemParadox - nada, aunque 'WHERE 1 = 0' es más portable si alguien se encuentra con este que está trabajando con un DBMS diferente. Por ejemplo, SQL Server no aceptará 'WHERE FALSE'. –

6

Sé que esto es una repetición de otras respuestas, pero tiene algo de apoyo emocional para tomar la medida adicional para la actualización de la prueba: D

Para la actualización de prueba, almohadilla # es su amigo.

Si tiene una instrucción de actualización como:

UPDATE 
wp_history 
SET history_by="admin" 
WHERE 
history_ip LIKE '123%' 

Usted hash de UPDATE y establecidos para las pruebas, entonces el hash de nuevo en:

SELECT * FROM 
#UPDATE 
wp_history 
#SET history_by="admin" 
WHERE 
history_ip LIKE '123%' 

Funciona para declaraciones simples.

Una solución adicional prácticamente obligatoria es, para obtener una copia (copia de seguridad duplicada), cada vez que utilice la actualización en una tabla de producción. Phpmyadmin> operations> copy: table_yearmonthday. Solo lleva unos segundos para las tablas < = 100M.

33

¿Qué ocurre con las transacciones? Tienen el ROLLBACK-Feature.

@see https://dev.mysql.com/doc/refman/5.0/en/commit.html

Por ejemplo:

START TRANSACTION; 
SELECT * FROM nicetable WHERE somthing=1; 
UPDATE nicetable SET nicefield='VALUE' WHERE somthing=1; 
SELECT * FROM nicetable WHERE somthing=1; #check 

COMMIT; 
# or if you want to reset changes 
ROLLBACK; 

SELECT * FROM nicetable WHERE somthing=1; #should be the old value 

respuesta en la pregunta de @rickozoe a continuación:

En general no se ejecutarán una vez que estas líneas. En PHP f.e. que iba a escribir algo así (tal vez un poco más limpia, pero quería responder rápida ;-)):

$MysqlConnection->query('START TRANSACTION;'); 
$erg = $MysqlConnection->query('UPDATE MyGuests SET lastname='Doe' WHERE id=2;'); 
if($erg) 
    $MysqlConnection->query('COMMIT;'); 
else 
    $MysqlConnection->query('ROLLBACK;'); 

Otra manera sería utilizar variables de MySQL (ver https://dev.mysql.com/doc/refman/5.7/en/user-variables.htm l y https://stackoverflow.com/a/18499823/1416909 ):

# do some stuff that should be conditionally rollbacked later on 

SET @v1 := UPDATE MyGuests SET lastname='Doe' WHERE id=2; 
IF(v1 < 1) THEN 
    ROLLBACK; 
ELSE 
    COMMIT; 
END IF; 

Pero le sugiero que utilice los envoltorios de idioma disponibles en su lenguaje de programación favorito.

+0

Buen enfoque seguro, gracias. – input

+0

Esto tendrá resultados inesperados con las transacciones anidadas. – scones

+0

¿Puedes dar un ejemplo? –

Cuestiones relacionadas