PHP - How to import csv file when mysql server doesnt allow load infile

in #developer5 years ago

here's another slick piece for my big-data pals

Most web host providers using shared hosting disable the mysql load infile feature due to security risks with all users basically on the same machine.

So, i came up with this quick little recursive function

  • it can import a 10mb file with 30k rows (38 cols/row) in ~60 seconds

still not as fast as ~.5 seconds using load infile - but still WAY faster than doing 30k single "insert into"

So i use https://fatfreeframework.com/ - super small and super fast

you should be able to adapt this to your platform fairly easy.

/*

    @file[csv] - take a csv file(absolute path) - recursive batch insert
    @start[int] - row number to start chunk
    @chunk[int] - how many rows to insert

*/
public function batch( $file , $start=0 , $chunk=1024){
    $count = 0;

    $table = basename( $file , '.csv');

    $rows = []; //empty array for batch insert rows (quoted)

    $fp = @fopen($file , "r");
    while( 
        ($row = fgetcsv($fp)) !== false &&
        count($rows) < $chunk
    ){
        //this first line skips the header row - adjust for your csv
        if(stripos($row[0] , 'Item ID') === false && $count > $start){
        
            $quoted = [];   //empty array for column data
            
            //loop through cols(header) to truncate row (make sure row is the right size)
            //if you do import with crappy csv (extra columns) - it breaks everything
            //so we just get rid of un-needed data
            
            //make sure you have your table field names in an ordered array that matches the csv columns
            foreach($this->csv->fields(false) as $k => $field){   //false = don't load virtual fields
            
                $quoted[] = $this->db->quote($row[$k]); //make sure all entries are quoted
                
            }
            $rows[] = "(" . join("," , $quoted) . ")";  //create string for values ()
        }

        $count++;
    }//end - read $chunk rows
    fclose($fp);

    $row_count = count($rows);

    if( $row_count > 0){
        $query = "insert into `{$table}` values " . join("," , $rows);
        $this->db->exec( $query );
        return $this->batch( $file , $count);   //keep going until we run out of rows
    }

    return; //we only get this far if no more rows to read
}//end function

well that's it for today boys and girls - have fun.

Coin Marketplace

STEEM 0.29
TRX 0.11
JST 0.033
BTC 63458.69
ETH 3084.37
USDT 1.00
SBD 3.99