2010-05-14 5 views
11

Задолго до того, как я что-то знал - не то, что я знаю многое даже сейчас - я отбросил веб-приложение в php, которое вставляло данные в мою базу данных mysql после запуска значений через htmlentities(). Я в конце концов опомнился и снял этот шаг и застрял на выходе, а не на входе, и продолжил свой веселый путь.Как удалить значения htmlentities() из базы данных?

Однако с тех пор мне пришлось пересмотреть некоторые из этих старых данных, и, к сожалению, у меня возникла проблема, когда она отображается на экране. Я получаю значения, которые эффективно отображаются htmlentitied дважды.

Итак, существует ли способ mysql или phpmyadmin изменить все старые, затронутые строки обратно на соответствующие символы или мне придется написать скрипт для чтения каждой строки, декодирования и обновления всех 17 миллионов строк в 12 таблицах?

EDIT:

Спасибо за помощь всем, я написал свой собственный ответ вниз с некоторым кодом в, это не очень, но он работал на тестовых данных ранее так запрещая кто-то указывая на явную ошибку в своем коде пока я нахожусь в постели, я буду запускать его на резервной БД завтра, а затем на живом, если все будет в порядке.

+0

Что с HTML сущностями? Они определенно подходят специально для неанглийских языков ... – nico

+0

Знакомая проблема, боюсь, я еще не решил ее ... – jeroen

+1

@nico нет ничего плохого в html-сущностях, просто я бы предпочитают данные, сохраненные по мере их ввода, его можно запускать через htmlentities при выходе. Это был выбор, который я сделал после того, как запустил сайт, хотя так требуется стандартизация для всех строк. – TooManyCooks

ответ

5

Я закончил с этим, не красивым, но я устал, это 2 часа ночи, и это сработало! (Редактирование: по данным испытаний)

$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

В ** MySQL ** вы можете сгенерировать список ** таблиц **, используя 'SHOW TABLES;' и в * * PostgreSQL ** сгенерирует список ** таблиц **, используя 'SELECT table_name FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema') ORDER BY table_name ASC;' если вы хотите сделать скрипт немного больше динамичный. – John

4

Поскольку PHP был методом кодирования, вы захотите его использовать для декодирования. Вы можете использовать html_entity_decode, чтобы преобразовать их обратно в исходные символы. Gotta loop!

Просто будьте осторожны, чтобы не расшифровать строки, которые ему не нужны. Не знаете, как вы это определите.

+0

Да, я знаю об использовании функции, и если мне нужно обновить каждую строку, я буду использовать ее, но я хотел бы знать, был ли более короткий способ сделать это в mysql или phpmyadmin, т. Е. Массовый обновление по затронутым строкам. Некоторая неясная функция, которую они скрывали от меня. – TooManyCooks

+0

@webbie как для вашей отредактированной точки, да, мне повезло, у меня есть старые резервные копии источника, который я написал, и файлы журналов, поэтому я точно знаю, когда код был изменен, и нос вокруг строк в БД вокруг этого время подтвердите это тоже. – TooManyCooks

+0

Whew. Хорошо, что ты это сделал! – webbiedave

2

Я думаю, что писать сценарий php - это хорошо, что нужно делать в этой ситуации. Вы можете использовать, как сказал Дэйв, функцию html_entity_decode() для преобразования ваших текстов назад.

Попробуйте выполнить свой сценарий на столе с небольшим количеством записей. Это позволит вам сэкономить много времени на тестирование. Конечно, не забудьте сделать резервную копию своих таблиц перед запуском php-скрипта.

Боюсь, что нет более короткой возможности. Вычисление для миллионов строк остается довольно дорогостоящим, независимо от того, как вы конвертируете данные. Так что для PHP скрипт ... это самый простой способ

+0

Да, это то, что я подозревал, однако я надеялся, что это своего рода полезная функция phpmyadmin, возможно, спрятала где-то, вместо того, чтобы делать это сама. По крайней мере, если я напишу, я могу поделиться им, я думаю. – TooManyCooks

+0

Я вижу ... Я хотел сказать, что даже если у phpMyAdmin была такая функция (она может быть), она просто выполнила бы запрос mysql через php. Вы ничего не сохранили бы с точки зрения времени выполнения и/или ресурсов. Но я думаю, что писать сценарий не должно быть так сложно в этом случае, и у вас будут прекрасные наборы данных :) – Simon

0

Это немного запутано, но я думаю, что обновление массы единственный путь ...

$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); 
} 

Это упрощается, никакой обработки ошибок и т. д. Не уверен, что время обработки будет на миллионы строк, поэтому вам может потребоваться разбить его на куски, чтобы избежать таймаутов в сценариях.

0

У меня была такая же проблема. Поскольку у меня было несколько клиентов, работающих под управлением приложения, я хотел избежать использования PHP-скрипта для очистки базы данных для каждого из них.

Я придумал решение, которое далека от совершенства, но делает работу безболезненно.

  1. Отслеживайте все пятна в коде, где вы используете htmlentities(), прежде чем вставлять данные и удалять их.
  2. Изменить свои "отображения данных в виде HTML" метод что-то вроде этого:

    возврата html_entity_decode (htmlentities ($ Chaine, ENT_NOQUOTES), ENT_NOQUOTES);

Процесс отмены отменен, но он выполняет эту работу. И ваша база данных будет медленно очищаться каждый раз, когда пользователи обновляют неверные данные.

0

Это моя пуленепробиваемая версия. Он выполняет итерацию по всем столбцам Tables и String в базе данных, определяет первичный ключ (ы) и выполняет обновления.

Предназначен для запуска php-файла из командной строки для получения информации о ходе работы.

<?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"; 
     } 
    } 
} 
?> 

веселит Roland

Смежные вопросы