¿Cómo probar una instrucción SQL Update antes de ejecutarla?


En algunos casos, ejecutar una instrucción UPDATE en production puede salvar el día. Sin embargo, una actualización borked puede ser peor que el problema inicial.

A falta de usar una base de datos de prueba, ¿cuáles son las opciones para saber qué hará una instrucción update antes de ejecutarla?

Author: static_rtti, 2012-06-13

7 answers

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

Así que si actualizas es

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

Lo siguiente le mostrará qué filas se actualizarán:

SELECT *
FROM foo
WHERE col1 = 1
  AND col2 = 'foobar';
 30
Author: a_horse_with_no_name,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-13 09:17:41

Apagado automático ...

MySQL

set autocommit=0;

Desactiva el autommit para la sesión actual.

Usted ejecuta su declaración, ver lo que ha cambiado, y luego revertir si está mal o confirmar si es lo que esperaba !

EDITAR: El beneficio de usar transacciones en lugar de ejecutar select query es que puede verificar el conjunto resultante con facilidad.

 46
Author: Imad Moqaddem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-31 14:17:29

¿Qué pasa con las transacciones? Tienen la función de REVERSIÓN.

@ ver 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 a la pregunta de @rickozoe a continuación:

En general, estas líneas no se ejecutarán como una sola vez. En PHP f. e. escribirías algo así (quizás un poco más limpio, pero querías responder rápido ;-) ):

$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 forma sería usar variables 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 sugeriría usar los envoltorios de lenguaje disponibles en su lenguaje de programación favorito.

 43
Author: Marcel Lange,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-19 16:42:04

Sé que esto es una repetición de otras respuestas, pero tiene algo de apoyo emocional para dar el paso adicional para probar la actualización: D

Para probar la actualización, hash # es tu amigo.

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

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

Se ACTUALIZA hash y se pone a prueba, luego 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), siempre que se utilice la actualización en una producción tabla. Phpmyadmin > operaciones > copiar: table_yearmonthday. Solo toma unos segundos para las tablas

 8
Author: Johan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-01 02:45:17

No es una respuesta directa, pero he visto muchas situaciones de datos borked prod que podrían haberse evitado escribiendo la cláusula WHERE primero! A veces un WHERE 1 = 0 puede ayudar a armar una declaración de trabajo de manera 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 otros han dicho.

 3
Author: David M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-13 09:08:23

Ejecute select query en la misma tabla con todas las condiciones where que está aplicando en update query.

 1
Author: manurajhada,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-13 08:59:18

Haz un SELECT de él,

Como si tuvieras

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

Convertirlo a

SELECT * FROM users WHERE name='jan'

 0
Author: EaterOfCode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-13 09:00:14