The best way to do this kind of thing is by using prepared statements and transactions with the help of PDO library. PDO is the simplest choice for any DB interaction in PHP.
Prepared statements are fast, easy and they offer parameter binding which will protect you from SQL injection as a side effect.
DB transactions ensure that all the data is inserted or none at all. They can also significantly improve the performance of such kind of task.
Here is an example code:
// create new connection to MySQL using PDO class
$pdo = new \PDO("mysql:host=$host;dbname=$db;charset=$charset", $user, $pass, [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_EMULATE_PREPARES => false
]);
$array = array(
array('name', 'age', 'gender'),
array('Ian', 24, 'male'),
array('Janice', 21, 'female')
);
// discard the header row (1st row) from the array
array_shift($array);
// start transaction
$pdo->beginTransaction();
// prepre SQL statemenet with 3 placeholders
$stmt = $pdo->prepare('INSERT INTO csv_table(name, age, gender) VALUES(?,?,?)');
foreach ($array as $row) {
$stmt->execute($row);
}
// end transaction
$pdo->commit();
What about the header row?
As you can see in the code above I am discarding the header row. Since SQL tables are rigid I need to know beforehand what are the names of columns. If you want to match columns in the CSV to the columns in your schema dynamically then you need to add some logic which will look at a hardcoded list of columns (you can also fetch this information from information_schema
) and match it with the names of columns from your CSV.
The code can be adjusted as follows. Iterate over the column names from CSV and throw an exception if any of the columns are not defined in your code. If all columns are verified then implode()
the column names and inject that into your SQL string.
$array = array(
array('name', 'age', 'gender'),
array('Ian', 24, 'male'),
array('Janice', 21, 'female')
);
$table_columns = ['age', 'gender', 'name'];
// Validate CSV header row (1st row) against your schema columns
$header = array_shift($array);
foreach ($header as $col_name) {
if (!in_array($col_name, $table_columns, true)) {
throw new \Exception('Incorrect column name specified in CSV file');
}
}
// start transaction
$pdo->beginTransaction();
// prepre SQL statemenet with 3 placeholders
$stmt = $pdo->prepare('INSERT INTO csv_table('.implode(',', $header).') VALUES(?,?,?)');
foreach ($array as $row) {
$stmt->execute($row);
}
// end transaction
$pdo->commit();