2010-05-14 17 views
11

在我知道任何东西之前很久 - 并非我现在知道的很多 - 我在php中设置了一个web应用程序,它在通过htmlentities()运行值后将数据插入我的mysql数据库。我终于明白我的意思,并取消了这一步,并把它放在输出而不是输入中,然后继续我的快乐之路。如何从数据库中删除htmlentities()值?

但是我从此不得不重新访问这些旧的数据,不幸的是我有一个问题,当它显示在屏幕上时,我得到的值显示的有效值是两次。

那么,是否有mysql或phpmyadmin方式将所有较旧的受影响的行更改回相关字符,还是必须编写一个脚本来读取每行,解码并更新12个表中的所有1700万行?

编辑:

感谢大家的帮助,我有一些代码写我自己的答案下面下来,这是不漂亮,但它的工作对测试数据较早所以除非有人指出我的代码中一个明显的错误在我睡觉的时候,我会在明天备份数据库上运行它,然后在活着的数据库上运行它,如果这样做没问题的话。

+0

有什么不对HTML实体?他们肯定是特别适合非英语语言的方式...... – nico 2010-05-14 23:32:31

+0

熟悉的问题,恐怕我还没有解决它... – jeroen 2010-05-14 23:36:01

+1

@nico html实体没有错,只是我想更喜欢输入时存储的数据,输出时可以通过htmlentities运行。这是我在启动网站后所做的选择,尽管如此需要对所有行进行标准化。 – TooManyCooks 2010-05-14 23:38:26

回答

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 2015-09-06 20:36:53

4

由于PHP是编码的方法,因此您需要使用它进行解码。您可以使用html_entity_decode将它们转换回原始字符。要循环!

只要小心不要解码不需要它的行。不知道你将如何确定。

+0

是的,我知道这个函数的用法,如果我必须更新每一行,我会使用它,但我想知道是否有一个更简单的方法在mysql或phpmyadmin中执行它,更新受影响的行。他们躲避我的一些模糊功能。 – TooManyCooks 2010-05-14 23:32:09

+0

@webbie至于你的编辑点,是的,我很幸运,我有我写的源代码和日志文件的旧备份,所以我确切知道代码被更改的时间,并围绕着数据库中的行时间也确认。 – TooManyCooks 2010-05-14 23:40:11

+0

噢。好东西你做到了! – webbiedave 2010-05-15 01:00:28

2

我觉得编写一个php脚本在这种情况下是件好事。正如Dave所说,您可以使用html_entity_decode()函数将文本转换回来。

请先尝试使用少量条目的表格,这会让你节省很多测试时间。当然,记得在运行php脚本之前备份你的表。

恐怕不会有更短的可能性。无论您如何将数据集转换回来,对数百万行的计算仍然相当昂贵。所以要为一个PHP脚本...这是这是一个有点缺憾的最简单的方法

+0

是的,这是我怀疑的,但我一直希望这是一种有用的功能phpmyadmin可能已经隐藏在某个地方,而不是自己做。至少如果我写它,我可以分享它。 – TooManyCooks 2010-05-14 23:42:08

+0

我看到......我想说的是,即使phpMyAdmin有这样一个函数(它可能有),它只会通过php执行一个mysql查询。您不会在执行时间和/或资源方面保存任何内容。但我认为在这种情况下编写脚本应该不会那么困难,并且您将拥有良好的数据集:) – Simon 2010-05-14 23:47:49

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(ヶ辆($ CHAINE,ENT_NOQUOTES),ENT_NOQUOTES);

undo-redo过程有点荒谬,但它的确有用。每当用户更新不正确的数据时,您的数据库就会慢慢清理自己。

0

这是我的防弹版。它迭代数据库中的所有表和字符串列,确定主键并执行更新。

它旨在从命令行运行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"; 
     } 
    } 
} 
?> 

欢呼 罗兰