Вставить данные CSV в базу данных с одинарной кавычкой в ​​данных - PullRequest
0 голосов
/ 02 декабря 2011
if (($handle = fopen($source_file, "r")) !== FALSE) {
    $columns = fgetcsv($handle, $max_line_length, ",");
    foreach ($columns as &$column) {
        $column = str_replace(".","",$column);
    }
    while (($data = fgetcsv($handle, $max_line_length, ",")) !== FALSE) {
        while(count($data) < count($columns)) {
            array_push($data, NULL);
        }
        $c = count($data);
        for($i = 0; $i < $c; $i++) {
            $data[$i] = "'{$data[$i]}'";
        }

        $sql[] = '(' . implode(',', $data) . ", '" . $_POST['custgroup'] . "'," . $_POST['user_id'] . ')';
    }

 $db = new PDO("mysql:host=localhost;dbname=test;","root",""); 

 $insert = $db->prepare("INSERT INTO $target_table (". implode(',', $columns) .',custgroup,user_id) VALUES ' .implode(',', $sql));
 $insert->execute();

У меня есть такой скрипт, который будет вставлять данные CSV в базу данных в соответствии с заголовком, и 2 дополнительных данных, которые являются идентификатор группы и пользователя.Это работает хорошо, но когда мое имя в CSV-файле Sher's Aria, то оно будет иметь ошибку. Я знаю, что это из-за одинарной кавычки символа в имени ', так что я могу сделать, чтобы решить эту проблему, чтобы любойИмя с одинарной кавычкой также можно вставить?

Спасибо.

Редактировать:

function csv_file_to_mysql_table($source_file, $target_table, $max_line_length=10000) {

if($source_file != '')
  {

    if (($handle = fopen($source_file, "r")) !== FALSE) {
     $columns = fgetcsv($handle, $max_line_length, ",");
     $esc_columns = array();
         foreach ($columns as &$column) {
            $column = str_replace(".","",$column);
            $esc_columns[] = escapeSqlName($column);
          }

      $esc_columns[] = escapeSqlName('custgroup');
      $esc_columns[] = escapeSqlName('user_id');

      $sqlsmttempl = 'INSERT INTO %s (%s) VALUES (%s)';
      $sqlsmt = sprintf($sqlstmttempl,
      escapeSqlName($target_table), 
      implode(',', $esc_columns), 
      implode(',',array_fill(0, count($esc_columns), '?')) // the parameter placeholders
 );

$db = new PDO("mysql:host=localhost;dbname=test;","root",""); 

$insert = $db->prepare($sqlsmt);  

while (($data = fgetcsv($handle, $max_line_length, ",")) !== FALSE) {
    while(count($data) < count($columns)) {
        $data[] = NULL;
    }
    $data[] = $_POST['custgroup'];
    $data[] = $_POST['user_id'];


 if($insert->execute($data))
 {
   header("Location:customer-search.php");
 }
else
{
echo "no";
 }

}

 fclose($handle);
   }
 }


if (isset($_POST['submit'])) {

$file = $_FILES['filename']['tmp_name'];
$table = 'UserAddedRecord';

csv_file_to_mysql_table($file,$table);
}

Ответы [ 4 ]

2 голосов
/ 02 декабря 2011

Вы уже используете PDO, поэтому вы должны заставить PDO обрабатывать ваше побег за вас с вашим подготовленным заявлением. Код ниже делает это.

Обратите внимание, что у вас все еще есть проблема безопасности, потому что вы назначаете таблицу и имена столбцов динамически. Приведенный ниже код пытается убедиться, что это не привести к любым SQL-инъекциям, но вы все равно должны быть осторожны.

Но у вас не будет проблем с неэкранированным вводом в часть VALUES(), и вставки должны быть намного быстрее, так как вы готовите заявление только один раз.

function escapeSqlName($name, $quotechar='`') {
        // This is to escape column names. This $quotechar ONLY WORKS WITH MYSQL
        // ANSI syntax is to use $quotechar='"' and double them where-ever " is in the table name.
        return $quotechar.str_replace($quotechar, $quotechar.$quotechar, $name).$quotechar;
}

if (($handle = fopen($source_file, "r")) !== FALSE) {
    $columns = fgetcsv($handle, $max_line_length, ",");
    $esc_columns = array();
    foreach ($columns as &$column) {
        $column = str_replace(".","",$column);
        $esc_columns[] = escapeSqlName($column);
    }
    // your two extra columns
    $esc_columns[] = escapeSqlName('custgroup');
    $esc_columns[] = escapeSqlName('user_id');

    $sqlsmttempl = 'INSERT INTO %s (%s) VALUES (%s)';
    $sqlsmt = sprintf($sqlsmttempl,
        escapeSqlName($target_table), // the escaped table name
        implode(',', $esc_columns), // the escaped column names
        implode(',',array_fill(0, count($esc_columns), '?')) // the parameter placeholders
    );
    // $sqlsmt should now look like 'INSERT INTO `thetable` (`col1`,`col2`,...) VALUES (?,?,...)';

    $db = new PDO("mysql:host=localhost;dbname=test;","root",""); 

    $insert = $db->prepare($sqlsmt);  // prepare statement ONCE, execute with new values MULTIPLE TIMES

    while (($data = fgetcsv($handle, $max_line_length, ",")) !== FALSE) {
        while(count($data) < count($columns)) {
            $data[] = NULL;
        }
        // your two extra values
        $data[] = $_POST['custgroup'];
        $data[] = $_POST['user_id'];

        $insert->execute($data); // does data escaping for you.
    }
}
1 голос
/ 02 декабря 2011

Одним из преимуществ (или, возможно, даже целью) подготовленных отчетов является разделение фактического отчета и его параметров (данных о зарплате).
Вместо построения строки, содержащей данные о зарплате, вы должны связать эти параметры с помощью PDOStatement :: bindParam или PDOStatement :: bindValue .

0 голосов
/ 02 декабря 2011

Используйте

mysql_real_escape_string

для каждой записи в файле csv перед вставкой значения в массив.

так, замените

$data[$i] = "'{$data[$i]}'";

с

$data[$i] = "'".mysql_real_escape_string($data[$i])."'";
0 голосов
/ 02 декабря 2011

Выход из CSV

Окружите свои поля кавычками, чтобы они содержали апострофы в файле CSV.Например, в вашем CSV:

"title", "name"
"Mr", "O'Hara"

Экранирование базы данных

Вы должны смотреть на экранирование данных с использованием PDO, как подсказывает @VolkerK.

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