2010-05-14 36 views
11

Lâu trước khi tôi biết bất cứ điều gì - không phải là tôi biết nhiều ngay cả bây giờ - Tôi đã xác định một ứng dụng web trong php mà chèn dữ liệu trong cơ sở dữ liệu mysql của tôi sau khi chạy các giá trị thông qua htmlentities(). Tôi cuối cùng đã đến giác quan của tôi và loại bỏ bước này và bị mắc kẹt trong đầu ra chứ không phải là đầu vào và đi trên con đường vui vẻ của tôi.Làm thế nào để loại bỏ htmlentities() giá trị từ cơ sở dữ liệu?

Tuy nhiên tôi đã phải xem lại một số dữ liệu cũ này và tiếc là tôi gặp sự cố khi hiển thị trên màn hình tôi nhận được các giá trị được hiển thị có hiệu quả hai lần. Vì vậy, có một mysql hoặc phpmyadmin cách thay đổi tất cả các hàng cũ hơn, bị ảnh hưởng trở lại vào các nhân vật có liên quan của họ hoặc tôi sẽ phải viết một kịch bản để đọc mỗi hàng, giải mã và cập nhật tất cả 17 triệu hàng trong 12 bảng?

EDIT:

Thanks for the help tất cả mọi người, tôi đã viết câu trả lời của riêng tôi xuống dưới với một số mã trong, nó không đẹp nhưng nó làm việc trên các dữ liệu thử nghiệm trước để chặn một người nào đó chỉ ra một lỗi rõ ràng trong mã của tôi trong khi tôi đang ở trên giường tôi sẽ chạy nó trên một DB sao lưu vào ngày mai và sau đó trên một sống nếu điều đó hoạt động ra alright.

+0

Có gì sai với thực thể HTML? Họ chắc chắn là con đường để đi đặc biệt cho các ngôn ngữ không phải tiếng Anh ... – nico

+0

Vấn đề quen thuộc, tôi sợ rằng tôi chưa giải quyết được ... – jeroen

+1

@nico không có gì sai với các thực thể html, chỉ cần tôi thích dữ liệu được lưu trữ khi nó được nhập vào, nó có thể chạy qua htmlentities khi xuất. Đó là một sự lựa chọn tôi đã thực hiện sau khi đã bắt đầu trang web mặc dù vậy cần tiêu chuẩn hóa cho tất cả các hàng. – TooManyCooks

Trả lời

5

Tôi đã kết thúc bằng cách sử dụng này, không đẹp, nhưng tôi mệt mỏi, đó là 2 giờ sáng và nó đã làm công việc của mình! (Chỉnh sửa: trên dữ liệu thử nghiệm)

$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

Trong ** MySQL ** bạn có thể tạo danh sách ** bảng ** bằng cách sử dụng 'SHOW TABLES;' và trong * * PostgreSQL ** tạo danh sách ** bảng ** bằng cách sử dụng 'SELECT table_name FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema') ORDER BY table_name ASC;' nếu bạn muốn làm cho kịch bản thêm một chút năng động. – John

4

Vì PHP là phương thức mã hóa, bạn sẽ muốn sử dụng nó để giải mã. Bạn có thể sử dụng html_entity_decode để chuyển đổi chúng trở về ký tự ban đầu của chúng. Gotta loop!

Chỉ cần cẩn thận để không giải mã các hàng không cần. Không chắc chắn cách bạn sẽ xác định điều đó.

+0

Vâng, tôi biết về việc sử dụng chức năng và nếu tôi phải cập nhật mỗi hàng tôi sẽ sử dụng nó, nhưng tôi muốn biết nếu có một cách ngắn hơn để làm điều đó trong mysql hoặc phpmyadmin, tức là một khối lượng cập nhật trên các hàng bị ảnh hưởng. Một số chức năng che khuất họ trốn khỏi tôi. – TooManyCooks

+0

@webbie như điểm chỉnh sửa của bạn, tôi may mắn, tôi có bản sao lưu cũ của nguồn tôi đã viết và tệp nhật ký để tôi biết chính xác khi nào mã đã bị thay đổi và đi sâu vào các hàng trong DB xung quanh thời gian xác nhận nó quá. – TooManyCooks

+0

Whew. Điều tốt bạn đã làm điều đó! – webbiedave

2

Tôi nghĩ rằng viết một kịch bản php là điều tốt để làm trong tình huống này. Bạn có thể sử dụng, như Dave đã nói, hàm html_entity_decode() để chuyển đổi văn bản của bạn trở lại.

Hãy thử tập lệnh của bạn trên một bảng có ít mục nhập trước tiên. Điều này sẽ giúp bạn tiết kiệm rất nhiều thời gian thử nghiệm. Tất nhiên, hãy nhớ sao lưu (các) bảng của bạn trước khi chạy tập lệnh php.

Tôi e rằng không có khả năng ngắn hơn. Tính toán cho hàng triệu hàng vẫn còn khá tốn kém, bất kể bạn chuyển đổi các tập dữ liệu như thế nào. Vì vậy, đi cho một kịch bản php ... đó là cách dễ nhất

+0

Vâng đó là những gì tôi nghi ngờ, tuy nhiên tôi đã hy vọng đó là loại chức năng hữu ích phpmyadmin có thể đã ẩn đi một nơi nào đó, hơn là phải làm điều đó bản thân mình. Ít nhất nếu tôi viết nó tôi có thể chia sẻ nó tôi đoán. – TooManyCooks

+0

Tôi hiểu ... Những gì tôi muốn nói là ngay cả khi phpMyAdmin có một chức năng như vậy (nó có thể có), nó sẽ chỉ thực hiện truy vấn mysql thông qua php. Bạn sẽ không lưu bất cứ điều gì về thời gian thực hiện và/hoặc tài nguyên. Nhưng tôi nghĩ rằng viết một kịch bản không phải là khó trong trường hợp này và bạn sẽ có bộ dữ liệu tốt :) – Simon

0

Đó là một chút kludgy nhưng tôi nghĩ rằng bản cập nhật hàng loạt là cách duy nhất để đi ...

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

này được đơn giản hóa, không xử lý lỗi v.v. Không chắc chắn thời gian xử lý sẽ là hàng triệu hàng, do đó bạn có thể cần chia nhỏ thành nhiều phần để tránh hết thời gian chờ tập lệnh.

0

Tôi đã gặp vấn đề tương tự. Vì tôi có nhiều khách hàng đang chạy ứng dụng trong sản xuất, tôi muốn tránh chạy một tập lệnh PHP để làm sạch cơ sở dữ liệu cho mỗi một trong số chúng.

Tôi đã đưa ra một giải pháp hoàn hảo, nhưng công việc không đau đớn.

  1. Theo dõi tất cả các điểm trong mã của bạn nơi bạn sử dụng htmlentities() trước khi chèn dữ liệu và xóa dữ liệu đó.
  2. Thay đổi của bạn "hiển thị dữ liệu dưới dạng HTML" phương pháp để một cái gì đó như thế này:

    trở html_entity_decode (htmlentities ($ CHAINE, ENT_NOQUOTES), ENT_NOQUOTES);

Quá trình hoàn tác lại là vô lý, nhưng thực hiện công việc. Và cơ sở dữ liệu của bạn sẽ dần dần tự làm sạch mỗi khi người dùng cập nhật dữ liệu không chính xác.

0

Đây là phiên bản bằng chứng đạn của tôi. Nó lặp qua tất cả các cột Bảng và Chuỗi trong cơ sở dữ liệu, xác định (các) khóa chính và thực hiện các cập nhật.

Dự định chạy tệp php từ dòng lệnh để lấy thông tin tiến trình.

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

cổ vũ Roland

Các vấn đề liên quan