Как удалить значения htmlentities () из базы данных? - PullRequest
11 голосов
/ 15 мая 2010

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

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

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

EDIT:

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

Ответы [ 6 ]

5 голосов
/ 15 мая 2010

Я закончил тем, что использовал это, не очень, но я устал, было 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
            }
    }
4 голосов
/ 15 мая 2010

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

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

2 голосов
/ 15 мая 2010

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

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

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

1 голос
/ 02 ноября 2016

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

Он предназначен для запуска 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

0 голосов
/ 10 мая 2016

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

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

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

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

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

0 голосов
/ 15 мая 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...