2010-05-14 12 views
11

Mucho antes de saber algo, aunque no sé mucho, diseñé una aplicación web en php que insertaba datos en mi base de datos mysql después de ejecutar los valores en htmlentities(). Finalmente volví a mis sentidos y eliminé este paso y lo metí en la salida en lugar de hacerlo, y seguí mi camino feliz.¿Cómo eliminar los valores de htmlentities() de la base de datos?

Sin embargo, he tenido que volver a visitar algunos de estos datos antiguos y, lamentablemente, tengo un problema, cuando se muestra en la pantalla obtengo valores que se htmlentitied de manera efectiva dos veces.

Entonces, ¿existe alguna forma de mysql o phpmyadmin de cambiar todas las filas antiguas afectadas por sus caracteres relevantes o tendré que escribir un script para leer cada fila, decodificar y actualizar las 17 millones de filas en 12 tablas?

EDIT:

Gracias por la ayuda de todos, escribí mi propia respuesta abajo con un poco de código en, no es bonito pero trabajaron en los datos de prueba de modo de restricción antes alguien señalando un error evidente en mi código Mientras estoy en la cama lo ejecutaré en una base de datos de respaldo mañana y luego en el vivo si funciona bien.

+0

¿Qué pasa con las entidades HTML? Definitivamente son el camino a seguir, especialmente para idiomas que no están en inglés ... – nico

+0

Problema familiar, me temo que aún no lo he resuelto ... – jeroen

+1

@nico no hay nada de malo con las entidades html, solo que lo haría prefiere los datos almacenados tal como se ingresaron, se puede ejecutar a través de htmlentities cuando se imprimen. Fue una elección que hice después de haber comenzado el sitio, así que necesita estandarización para todas las filas. – TooManyCooks

Respuesta

5

Terminé usando esto, no es bonito, pero estoy cansado, son las 2am y ¡hizo su trabajo! (Editar: en datos de prueba)

$tables = array('users', 'users_more', 'users_extra', 'forum_posts', 'posts_edits', 'forum_threads', 'orders', 'product_comments', 'products', 'favourites', 'blocked', 'notes'); 
foreach($tables as $table) 
    {  
     $sql = "SELECT * FROM {$table} WHERE data_date_ts < '{$encode_cutoff}'"; 
     $rows = $database->query($sql); 
     while($row = mysql_fetch_assoc($rows)) 
      { 
       $new = array(); 
       foreach($row as $key => $data) 
        { 
         $new[$key] = $database->escape_value(html_entity_decode($data, ENT_QUOTES, 'UTF-8')); 
        } 
       array_shift($new); 
       $new_string = ""; 
       $i = 0; 
       foreach($new as $new_key => $new_data) 
        { 
         if($i > 0) { $new_string.= ", "; } 
         $new_string.= $new_key . "='" . $new_data . "'"; 
         $i++; 
        } 
       $sql = "UPDATE {$table} SET " . $new_string . " WHERE id='" . $row['id'] . "'"; 
       $database->query($sql); 
       // plus some code to check that all out 
      } 
    } 
+0

En ** MySQL ** puedes generar una lista de ** tablas ** usando 'MOSTRAR TABLAS;' y en * * PostgreSQL ** genera una lista de ** tablas ** usando 'SELECT table_name FROM information_schema.tables WHERE tabla_schema NOT IN ('pg_catalog', 'information_schema') ORDER BY table_name ASC;' si desea hacer el script un poco más dinámica. – John

4

Como PHP era el método de codificación, querrá usarlo para decodificar. Puede usar html_entity_decode para convertirlos a sus caracteres originales. Tengo un lazo!

Solo tenga cuidado de no decodificar filas que no lo necesitan. No estoy seguro de cómo va a determinar eso.

+0

Sí, soy consciente del uso de la función y si tengo que actualizar cada fila, la usaré, pero quería saber si había una forma más corta de hacerlo en mysql o phpmyadmin, es decir, en una masa. actualización en las filas afectadas. Alguna oscura función me ocultaron. – TooManyCooks

+0

@webbie en cuanto a su punto editado, sí tengo suerte, tengo las copias de seguridad anteriores de la fuente que escribí y los archivos de registro, así sé exactamente cuándo se modificó el código, y curiosear en las filas en el DB alrededor de ese el tiempo lo confirma también – TooManyCooks

+0

Whew. ¡Qué bueno que lo hiciste! – webbiedave

2

Creo que escribir una secuencia de comandos php es algo bueno que hacer en esta situación. Puede usar, como dijo Dave, la función html_entity_decode() para convertir sus mensajes de texto.

Primero pruebe su secuencia de comandos en una tabla con algunas entradas. Esto le ahorrará mucho tiempo de prueba. Por supuesto, recuerde hacer una copia de seguridad de su mesa (s) antes de ejecutar el script php.

Me temo que no hay una posibilidad más corta. El cálculo para millones de filas sigue siendo bastante caro, sin importar cómo se conviertan los conjuntos de datos. Así que ir a un script php ... es la manera más fácil

+0

Sí, es lo que sospechaba, sin embargo, había esperado que fuera el tipo de función útil que phpmyadmin podría haber escondido en alguna parte, en lugar de tener que hacerlo yo mismo. Al menos si lo escribo puedo compartirlo, supongo. – TooManyCooks

+0

Ya veo ... Lo que quería decir es que incluso si phpMyAdmin tuviera esa función (puede tener), simplemente ejecutaría una consulta de mysql a través de php. No ahorrarías nada en términos de tiempo de ejecución y/o recursos. Pero creo que escribir un guión no debería ser tan difícil en este caso y tendrás conjuntos de datos precisos :) – Simon

0

Es un poco kludgy pero creo que la actualización masiva es la única manera de ir ...

$Query = "SELECT row_id, html_entitied_column FROM table"; 
$result = mysql_query($Query, $connection); 
while($row = mysql_fetch_array($result)){ 
    $updatedValue = html_entity_decode($row['html_entitied_column']); 
    $Query = "UPDATE table SET html_entitied_column = '" . $updatedValue . "' "; 
    $Query .= "WHERE row_id = " . $row['row_id']; 
    mysql_query($Query, $connection); 
} 

Esto se simplifica, ningún control de errores etc. No estoy seguro de cuál sería el tiempo de procesamiento en millones de filas, por lo que podría necesitar dividirlo en fragmentos para evitar el tiempo de espera de los scripts.

0

Tuve exactamente el mismo problema. Como tenía varios clientes ejecutando la aplicación en producción, quería evitar ejecutar un script PHP para limpiar la base de datos para cada uno de ellos.

Se me ocurrió una solución que está lejos de ser perfecta, pero que hace el trabajo sin dolor.

  1. Realice un seguimiento de todos los puntos en su código donde usa htmlentities() antes de insertar datos, y elimínelos.
  2. cambiar su "mostrar datos como HTML" método para algo como esto:

    html_entity_decode retorno (htmlentities ($ chaine, ENT_NOQUOTES), ENT_NOQUOTES);

El proceso de deshacer es algo ridículo, pero cumple su función. Y su base de datos se limpiará lentamente cada vez que los usuarios actualicen los datos incorrectos.

0

Esta es mi versión a prueba de balas. Se repite en todas las columnas de tablas y cadenas en una base de datos, determina la (s) clave (s) primaria (s) y realiza actualizaciones.

Está destinado a ejecutar el archivo php desde la línea de comandos para obtener información sobre el progreso.

<?php 
$DBC = new mysqli("localhost", "user", "dbpass", "dbname"); 
$DBC->set_charset("utf8"); 

$tables = $DBC->query("SHOW FULL TABLES WHERE Table_type='BASE TABLE'"); 
while($table = $tables->fetch_array()) { 
    $table = $table[0]; 
    $columns = $DBC->query("DESCRIBE `{$table}`"); 
    $textFields = array(); 
    $primaryKeys = array(); 
    while($column = $columns->fetch_assoc()) { 
     // check for char, varchar, text, mediumtext and so on 
     if ($column["Key"] == "PRI") { 
      $primaryKeys[] = $column['Field']; 
     } else if (strpos($column["Type"], "char") !== false || strpos($column["Type"], "text") !== false) { 
      $textFields[] = $column['Field']; 
     } 
    } 
    if (!count($primaryKeys)) { 
     echo "Cannot convert table without primary key: '$table'\n"; 
     continue; 
    } 
    foreach ($textFields as $textField) { 
     $sql = "SELECT `".implode("`,`", $primaryKeys)."`,`$textField` from `$table` WHERE `$textField` like '%&%'"; 
     $candidates = $DBC->query($sql); 
     $tmp = $DBC->query("SELECT FOUND_ROWS()"); 
     $rowCount = $tmp->fetch_array()[0]; 
     $tmp->free(); 
     echo "Updating $rowCount in $table.$textField\n"; 
     $count=0; 
     while($candidate = $candidates->fetch_assoc()) { 
      $oldValue = $candidate[$textField]; 
      $newValue = html_entity_decode($candidate[$textField], ENT_QUOTES | ENT_XML1, 'UTF-8'); 
      if ($oldValue != $newValue) { 
       $sql = "UPDATE `$table` SET `$textField` = '" 
        . $DBC->real_escape_string($newValue) 
        . "' WHERE "; 
       foreach ($primaryKeys as $pk) { 
        $sql .= "`$pk` = '" . $DBC->real_escape_string($candidate[$pk]) . "' AND "; 
       } 
       $sql .= "1"; 
       $DBC->query($sql); 
      } 
      $count++; 
      echo "$count/$rowCount\r"; 
     } 
    } 
} 
?> 

aplausos Roland

Cuestiones relacionadas