douwei9759 2017-02-23 15:24
浏览 154
已采纳

PHP / SQL - 将CSV上传到数据库 - 每天不同的工作表/多个表

I asked a question yesterday that was unclear and I've now expanded it slightly. In short, this current project calls for a simple web interface where the user can upload a csv file (this web page is created already). I've modified my PHP for a test file but my situation calls for something different. Every day, the user will upload 1 to 5 different CSV reports. These reports have about 110 fields/columns, though not all fields will be filled in every report. I've created a database with 5 tables, each table covering different fields out of the 110. For instance, one table holds info on the water meters (25 fields) and another table holds info for the tests done on the meters (45 fields). I'm having a hard time finding a way to take the CSV, once uploaded, and split the data into the different tables. I've heard of putting the whole CSV into one table and splitting from there with INSERT statements but I have questions with that:

  1. Is there a way to put a CSV with 110 fields into one table without having fields created? Or would I have to create 110 fields in MYSQL workbench and then create a variable for each in PHP?

  2. If not, would I be able to declare variables from the table dump so that the right data then goes into its correct table?

I'm not as familiar with CSVs in terms of uploading like this, usually just pulling a csv from a folder with a known file name, so that's where my confusion is coming from. Here is the PHP i've used as a simple test with only 10 columns. This was done to make sure the CSV upload works, which it does.

<?php

$server = "localhost";
$user = "root";
$pw = "root";
$db = "uwstest";

$connect = mysqli_connect($server, $user, $pw, $db);

if ($connect->connect_error) {
die("Connection failed: " . $conn->connect_error);
}


if(isset($_POST['submit']))
{
$file = $_FILES['file']['tmp_name'];
$handle = fopen($file, "r");
$c = 0;
while(($filesop = fgetcsv($handle, 1000, ",")) !== false)
{
 $one = $filesop[0];
 $two = $filesop[1];
 $three = $filesop[2];
 $four = $filesop[3];
 $five = $filesop[4];
 $six = $filesop[5];
 $seven = $filesop[6];
 $eight = $filesop[7];
 $nine = $filesop[8];
 $ten = $filesop[9];

 $sql = "INSERT INTO staging (One, Two, Three, Four, Five, Six, Seven,    Eight, Nine, Ten) VALUES ('$one','$two', '$three','$four','$five','$six','$seven','$eight','$nine','$ten')";
 }

 if ($connect->query($sql) === TRUE) {
 echo "You database has imported successfully";
 } else {
 echo "Error: " . $sql . "<br>" . $conn->error; 
 }
 }
 }?>
  • 写回答

2条回答 默认 最新

  • dpchen2004 2017-02-23 15:44
    关注

    Depending on CSV size, you might want to consider using MySQL's native CSV import function since it runs 10x-100x times faster.

    If you do insist on importing row by row, then you can do something like this with PDO (or adapt it to mysqli).

    If you want to match columns, then ,either store your csv as associative array, or parse first row and store it in in array like $cols.

    in this case, $results is an associative array that stores a row of csv with column_name=>column_value

    $cols=implode(',',array_keys($result));
      $vals=':'.str_replace(",",",:",$cols);
      $inserter = $pdo->prepare("INSERT INTO `mydb`.`mytable`($cols) VALUES($vals);");
    
       foreach ($result as $k => $v) {
       $result[':' . $k] = utf8_encode($v);
       if(is_null($v))
          $result[':' . $k] = null;
          unset($result[$k]);
        }
        $inserter->execute($result);
    

    hope this helps. I suggest going with PDO just to avoid all kinds of weirdness that you may encounter in CSV's data.

    This is how I would create columns/vals.

    $is_first=true;
    $cols='';
    $vals='';
    $cols_array=array();
    while (($csv = fgetcsv($handle)) !== false) {
    if($is_first)
    {
    $cols_array=$csv;
    $cols=implode(',',$csv);
    $is_first=false;
    $vals=':'.str_replace(",",",:",$cols);
    continue;
    }
    
    foreach ($result as $k => $v) {
       $result[':' . $cols_array[$k]] = utf8_encode($v);
       if(is_null($v))
          $result[':' . $cols_array[$k]] = null;
          unset($result[$k]);
        }
        $inserter->execute($result);
    }
    

    here is the code that I use for CSV imports.

            $file='data/data.csv';
            $handle = fopen($file, "r");
            $path=realpath(dirname(__FILE__));
            $full_path=$path."/../../$file";
            $cnt = 0;
            $is_first = true;
            $headers=array();
            $bind=array();
            $csv = fgetcsv($handle, 10000, ",");
            $headers=$csv;
            $alt_query='LOAD DATA LOCAL INFILE \''.$full_path.'\' INTO TABLE mytable 
                    FIELDS TERMINATED BY \',\'
                    ENCLOSED BY \'\"\'
                    LINES TERMINATED BY \'
    \'
                    IGNORE 1 LINES
                    (' . implode(',',$headers).')';
    
    echo exec("mysql -e \"USE mydb;$alt_query;\"",$output,$code);
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 有没有帮写代码做实验仿真的
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥30 vmware exsi重置后登不上
  • ¥15 MATLAB运行显示错误,如何解决?
  • ¥15 c++头文件不能识别CDialog
  • ¥15 Excel发现不可读取的内容
  • ¥15 关于#stm32#的问题:CANOpen的PDO同步传输问题
  • ¥20 yolov5自定义Prune报错,如何解决?