Reemplazar un texto por otro masivamente en Mysql

Ayer me tocó solucionar un problema… un sistema en joomla se fue desarrollando en un entorno de prueba y fue acumulando la url del mismo en la base de datos. Cuando el sistema salía a producción, hubo que cambiar la URL del entorno de pruebas por la URL definitiva del sitio en producción.

Este script también resulta útil cuando aparecen caracteres extraños al crear una base de datos desde un archivo .sql (dado que el juego de caracteres o charset del archivo es diferente al de la base de datos o bien al de la conexión de la base de datos).

Lo logramos utilizando la función Replace de MySQL, disponible en
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_replace

En el siguiente script sólo se deben completar el valor de los textos a buscar y reemplazar (además de los parámetros de la base de datos, claro está):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?php
header('Content-type: text/plain');
define('HOST', 'localhost');
define('DB', 'base_de_datos');
define('USER', 'usuario');
define('PASS', "password");
$textoBuscado = 'lo_que_dice';
$textoReemplazo = 'lo_que_debe_decir';
$i = 0;
/* Conector con base de datos */
$cnx = mysql_connect(HOST, USER, PASS) or trigger_error(mysql_error(), E_USER_ERROR);
@mysql_query("SET NAMES 'utf8'");
mysql_select_db(DB, $cnx);
/* Obtener listado de tablas */
$query_tablas = "SHOW TABLES";
$tablas = mysql_query($query_tablas, $cnx) or die(mysql_error());
$row_tablas = mysql_fetch_assoc($tablas);
$totalRows_tablas = mysql_num_rows($tablas);
/* Si existen tablas en la base de datos */
if ($totalRows_tablas > 0) {
  do {
    /* Obtener información de columnas */
    $query_columnas = sprintf("DESCRIBE `%s`", $row_tablas['Tables_in_' . DB]);
    $columnas = mysql_query($query_columnas, $cnx) or die(mysql_error());
    $row_columnas = mysql_fetch_assoc($columnas);
    $totalRows_columnas = mysql_num_rows($columnas);
    
    do {
      /* Esto se puede mejorar un poco...
       * en la bdd sólo habían campos de tipo text, char y varchar */
      
      /* Si la columna es de tipo texto */
      if (strpos($row_columnas['Type'], 'char') !== false ||
          $row_columnas['Type'] == 'text') {
        
        /* Construir la consulta de reemplazo para la columna específica */
        $query_rep = sprintf("UPDATE `%s` SET `%s`.`%s` = REPLACE(`%s`, '%s', '%s')",
          $row_tablas['Tables_in_' . DB],
          $row_tablas['Tables_in_' . DB],
          $row_columnas['Field'],
          $row_columnas['Field'],
          $textoBuscado,
          $textoReemplazo);
        $rep = mysql_query($query_rep, $cnx) or die(mysql_error());
        
        /* Obtener cantidad de filas actualizadas */
        $j = mysql_affected_rows();
        
        /* Mostrar cantidad de filas actualizadas */
        printf("Registros actualizados en columna [`%s`][`%s`]: %dn",
          $row_tablas['Tables_in_' . DB],
          $row_columnas['Field'],
          $j);
        
        /* Acumular filas actualizadas */
        $i += $j;
      }
    } while ($row_columnas = mysql_fetch_assoc($columnas));
  } while ($row_tablas = mysql_fetch_assoc($tablas));
}
/* Escribir cantidad total de filas modificadas */
echo 'En total se actualizaron ' . $i . ' registros.';
?>

Lo bueno es que el script recorre TODA la base de datos y no sólo una tabla en particular. Si se desea reemplazar una serie de elementos, pefectamente se pueden agregar los valores a buscar y reemplazar en un arreglo y luego iterar sobre el mismo para conseguirlo. Con un par de modificaciones menores, el script definitivo quedaría como esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<?php
header('Content-type: text/plain');
define('HOST', 'localhost');
define('DB', 'base_de_datos');
define('USER', 'usuario');
define('PASS', "password");
/* Habrá que asegurarse que estos arreglos tengan la misma cantidad de elementos */
$textoBuscado = array('lo_que_dice_1', 'lo_que_dice_2');
$textoReemplazo = array('lo_que_debe_decir_1', 'lo_que_debe_decir_2');
$k = 0;
/* Conector con base de datos */
$cnx = mysql_connect(HOST, USER, PASS) or trigger_error(mysql_error(), E_USER_ERROR);
@mysql_query("SET NAMES 'utf8'");
mysql_select_db(DB, $cnx);
for ($i = 0; $i < count($textoBuscado); $i++)
{
  /* Generar encabezado */
  echo "nReemplazando texto [" . $textoBuscado[$i] . "] en '" . DB . "'...n";
  /* Obtener listado de tablas */
  $query_tablas = "SHOW TABLES";
  $tablas = mysql_query($query_tablas, $cnx) or die(mysql_error());
  $row_tablas = mysql_fetch_assoc($tablas);
  $totalRows_tablas = mysql_num_rows($tablas);
  /* Si existen tablas en la base de datos */
  if ($totalRows_tablas > 0)
  {
    do
    {
      /* Obtener información de columnas */
      $query_columnas = sprintf("DESCRIBE `%s`", $row_tablas['Tables_in_' . DB]);
      $columnas = mysql_query($query_columnas, $cnx) or die(mysql_error());
      $row_columnas = mysql_fetch_assoc($columnas);
      $totalRows_columnas = mysql_num_rows($columnas);
      do
      {
        /* Esto se puede mejorar un poco...
        * en la bdd sólo habían campos de tipo text, char y varchar */
        /* Si la columna es de tipo texto */
        if (strpos($row_columnas['Type'], 'char') !== false ||
            $row_columnas['Type'] == 'text')
        {
          /* Construir la consulta de reemplazo para la columna específica */
          $query_rep = sprintf("UPDATE `%s` SET `%s`.`%s` = REPLACE(`%s`, '%s', '%s')",
            $row_tablas['Tables_in_' . DB],
            $row_tablas['Tables_in_' . DB],
            $row_columnas['Field'],
            $row_columnas['Field'],
            $textoBuscado[$i],
            $textoReemplazo[$i]);
          $rep = mysql_query($query_rep, $cnx) or die(mysql_error());
          /* Obtener cantidad de filas actualizadas */
          $j = mysql_affected_rows();
          /* Mostrar cantidad de filas actualizadas */
          if ($j > 0)
            printf("Registros actualizados en columna [`%s`][`%s`]: %dn",
              $row_tablas['Tables_in_' . DB],
              $row_columnas['Field'],
              $j);
          /* Acumular filas actualizadas */
          $k += $j;
        }
      } while ($row_columnas = mysql_fetch_assoc($columnas));
    } while ($row_tablas = mysql_fetch_assoc($tablas));
  }
  /* Escribir cantidad total de filas modificadas */
  echo 'En total se actualizaron ' . $k .
          ' registros que contenían el texto [' . $textoBuscado[$i] . '].';
  $k = 0;
}
?>

Deja un comentario

Cerrar menú