我想从Excel文件中做一些大量数据库填充。
最经济的方法是使用INSERT INTO
语句将大量值存储在一个事务中:
INSERT INTO `assortment`(`id`, `sku`, `agroup`, `subgroup`, `title`, `measure_unit`, `price`, `discount`, `imageUrl`, `fileUrl`)
VALUES ([value-1],[value-2],[value-3],[value-4],[value-5],[value-6],[value-7],[value-8],[value-9],[value-10]),
([value-1],[value-2],[value-3],[value-4],[value-5],[value-6],[value-7],[value-8],[value-9],[value-10]),
([value-1],[value-2],[value-3],[value-4],[value-5],[value-6],[value-7],[value-8],[value-9],[value-10]),
([value-1],[value-2],[value-3],[value-4],[value-5],[value-6],[value-7],[value-8],[value-9],[value-10]),
...
然而,为了避免SQL注入,我希望绑定params,yii为此提供functionality。然而,我似乎不可能为hundredes /成千上万的价值观做这件事。不是吗?
为了保持SQL hygene,我通过Active Record属性进行简单插入(Yii AR功能默认清理输入数据):
$auxarr = array();
for ($i = 0; $sheetData[$i]; $i++)
{
$model = new Assortment();
$j = 0;
foreach ($labels as $label)
{
$auxarr[$label] = $sheetData[$i][$j++];
}
$model->attributes = $auxarr;
if (!$model->save())
throw new CHttpException(400, 'Error db storing');
}
这种方法显然不合时宜。 在批量SQL插入中是否有任何兼容安全性和时间效率的方法?
答案 0 :(得分:1)
Yii在CDbCommand中使用传统的PDO。 因此,您可以创建一个由系列值组成的字符串,例如
(?,?,?),(?,?,?),(?,?,?),(?,?,?),(?,?,?),(?,?,?)
然后创建一个包含所有这些占位符的值的数组 最后执行所有的东西
答案 1 :(得分:1)
我的方法是
$sql = "INSERT INTO `assortment`(`id`, `sku`, `agroup`, `subgroup`, `title`, `measure_unit`, `price`, `discount`, `imageUrl`, `fileUrl`) VALUES "
$params = array();
$cntRows = count($sheetData);
for ($i = 0; $i < $cntRows; $i++)
{
$j = 0;
$rowParams = array();
foreach ($labels as $label)
{
$rowParams[":{$label}_{$i}_{j}"] = $sheetData[$i][$j++];
}
$params = array_merge($params, $rowParams);
$sql . = "(" . implode(",", array_keys($rowParams) ) .")"
}
/*
Sql now is : INSERT INTO assortment (....) VALUES ( :id_1_1 , sku_1_1 , ... ) (:id_2_1 , sku_2_1 , ...)
AND $params is { :id_1_1 => [value] ........ }
*/
$cmd = Yii::app()->db->createCommand($sql);
$cmd->execute($params);
我们在一个事务中执行insert sql,没有多个事务或使用ActiveRecord(浪费内存和许多函数被执行)并避免SQL注入。如果您的数据很大,您可以将其拆分为多个交易。