使用数据中的单引号将csv数据插入数据库

时间:2011-12-02 14:56:13

标签: php csv insert

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个额外的数据,即组和用户ID。它工作得很好,但是当我在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 个答案:

答案 0 :(得分:2)

您已经在使用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 :(得分:1)

准备好的声明的一个好处(或者甚至是目的)是实际声明及其参数(paylod数据)的分离。
您应该通过PDOStatement::bindParamPDOStatement::bindValue绑定这些参数,而不是构建包含paylod数据的字符串。

答案 2 :(得分:-1)

CSV转义

使用引号括起字段以包含CSV文件中的撇号。例如,在您的CSV中:

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

数据库转义

你应该看看使用PDO转发数据,如@VolkerK建议的那样。

答案 3 :(得分:-1)

使用

mysql_real_escape_string

在将值插入数组之前,对于csv文件中的每个条目

所以,替换

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

$data[$i] = "'".mysql_real_escape_string($data[$i])."'";