做这种事情的最好方法是在 PDO 库的帮助下使用准备好的语句和事务。 PDO 是 PHP 中任何数据库交互的最简单选择。
准备好的语句快速、简单,并且它们提供参数绑定,可以保护您免受 SQL 注入的副作用。
数据库事务确保所有数据都插入或根本不插入。它们还可以显着提高此类任务的性能。
这是一个示例代码:
// 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();
标题行呢?
正如您在上面的代码中看到的,我正在丢弃标题行。由于 SQL 表是刚性的,我需要事先知道列的名称是什么。如果您想动态地将 CSV 中的列与架构中的列进行匹配,那么您需要添加一些逻辑来查看硬编码的列列表(您也可以从 information_schema 获取此信息)并将其与名称匹配CSV 中的列数。
代码可以调整如下。如果您的代码中未定义任何列,则迭代 CSV 中的列名并引发异常。如果所有列都经过验证,则implode() 列名并将其注入您的 SQL 字符串。
$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();