There is a well-known from the network script import csv in the database Mysql. Everything works as it should, with one big and fat drawback that covers all the advantages. You need to import about 100 thousand lines. Everything works terribly long and for the most part does not end with success. Tell me, how is it better to rewrite the script so that it works more steadily? It is also possible to use PDO, but I am not strong in it.

if ($_FILES[csv][size] > 0) { //Получаем CSV файл $file = $_FILES[csv][tmp_name]; $handle = fopen($file,"r"); //Обрабатываем в цикле CSV файл и добавляем данные в БД do { if ($data[0]) { mysql_query("INSERT INTO price_minsk (brand, artikul, description, ostatok, kratnost, valuta, price) VALUES ( '".addslashes($data[0])."', '".addslashes($data[1])."', '".addslashes($data[2])."', '".addslashes($data[3])."', '".addslashes($data[4])."', '".addslashes($data[5])."', '".addslashes($data[6])."' ) "); } } while ($data = fgetcsv($handle,1000,";","'")); // //redirect header('Location: import.php?success=1'); die; } 

Also found such a function, which, as the manuals say, works quickly. But how to attach it to the above script?

 function import_csv( $table, // Имя таблицы для импорта $afields, // Массив строк - имен полей таблицы $filename, // Имя CSV файла, откуда берется информация // (путь от корня web-сервера) $delim=',', // Разделитель полей в CSV файле $enclosed='"', // Кавычки для содержимого полей $escaped='\\', // Ставится перед специальными символами $lineend='\\r\\n', // Чем заканчивается строка в файле CSV $hasheader=FALSE){ // Пропускать ли заголовок CSV if($hasheader) $ignore = "IGNORE 1 LINES "; else $ignore = ""; $q_import = "LOAD DATA INFILE '". $_SERVER['DOCUMENT_ROOT'].$filename."' INTO TABLE ".$table." ". "FIELDS TERMINATED BY '".$delim."' ENCLOSED BY '".$enclosed."' ". " ESCAPED BY '".$escaped."' ". "LINES TERMINATED BY '".$lineend."' ". $ignore. "(".implode(',', $afields).")" ; return mysql_query($q_import); } 
  • Just in case: using addslashes() to escape request parameters is incorrect - tutankhamun

1 answer 1

If you are allowed to access LOAD DATA INFILE , then of course you should use the function you found. Instead of a cycle, write simply:

 import_csv( 'price_minsk', array('brand', 'artikul', 'description', 'ostatok', 'kratnost', 'valuta', 'price'), $FILES['csv']['tmp_name'], ';', '\'' ); 

If you are not allowed this operation, you can modify your original function, but use the multi-line INSERT INTO

 if ($_FILES[csv][size] > 0) { //Получаем CSV файл $file = $_FILES[csv][tmp_name]; $handle = fopen($file,"r"); //Обрабатываем в цикле CSV файл и добавляем данные в БД $rowsToInsert = array(); $rowsCount = 100; $insertStmt = 'INSERT INTO price_minsk (`brand`, `artikul`, `description`, `ostatok`, `kratnost`, `valuta`, `price`) VALUES '; while ($data = fgetcsv($handle, 1000, ";", "'")) { if (7 == count($data)) { $row = array_map('mysql_real_escape_string', $data); $rowsToInsert[] = '("' . implode('", "', $row) . '")'; } //Если набралось достаточное количество строк if ($rowsCount <= count($rowsToInsert)) { mysql_query($insertStmt . implode(', ', $rowsToInsert)); $rowsToInsert = array(); } } //Если остались строки для добавления if (!empty($rowsToInsert)) { mysql_query($insertStmt . implode(', ', $rowsToInsert)); $rowsToInsert = array(); } //redirect header('Location: import.php?success=1'); die; } 

You can try to increase the $rowsCount to reasonable limits. The main max_allowed_packet that the length of the request does not exceed the limit ( max_allowed_packet ).

If necessary, you can rewrite it even to use mysqli even PDO . This is not important.

  • And on PDO or xPDO will it be materie for safety, speed, etc.? - Batyabest