简体   繁体   中英

PHP/SQL - Uploading CSV to database - Different sheets daily/Multiple Tables

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

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 \'\r\n\'
                IGNORE 1 LINES
                (' . implode(',',$headers).')';

echo exec("mysql -e \"USE mydb;$alt_query;\"",$output,$code);

假设表和CSV之间的关系是任意的,但现在是统一的,则只需建立一次对应数组索引->表列即可。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM