我有一个遍历数组的foreach循环。
在每个实例中,我将数组组织成一个查询字符串,并使用MySQLi将其添加到数据库中。
function storeProperties($data, $db) {
foreach ($data['property'] as $property) {
$query_string = "INSERT INTO table VALUES(..., ..., ...,)"
$db->query($query_string);
echo $db->error;
}
}
我应该采取更好的方式吗?
显然,这种方法一个接一个地使用 n 数据库查询,因此这是内存密集型和时间密集型的。
有更好的方法吗? 我应该将每个查询连接成一个字符串并在for循环之外运行吗?
答案 0 :(得分:0)
以下方法来自我的PDO主力,用于批量插入。它创建一个包含多个VALUES条目的INSERT语句。
将其用作
$db->bulkinsert(
'tbl_my_tablename',
array('fieldname_1','fieldname_2', 'fieldname_3'),
array(
/* rec1 */ array('r1f1', 'r1f2', 'r1f3'),
/* rec2 */ array('r2f1', 'r2f2', 'r2f3'),
/* rec3 */ array('r3f1', 'r3f2', 'r3f3')
));
请注意,该方法是来自复杂类定义的剪辑,此处使用的某些方法未包含在代码段中,尤其是$this->connect()
(连接到PDO),$this->begin()
(启动事务) ,$this->commit()
和$this->rollback()
,以及类似于Apache Commons的Logging静态Log
类; - )
但我确信这是你可能需要的。
/**
* Performs fast bulk insertion
* Parameters:
* $tablename
* $datafields - non-assiciative array of fieldnames
* or propertynames if $data is an array of objects
* $data - array of either non-associative arrays (in the correct order)
* or array of objects with property names matching the $datafields array
*/
const MAX_BULK_DATA = 3000;
public function bulkinsert($tablename, $datafields, &$data) {
$result = 0;
try {
try {
$this->connect();
$datacount = count($data);
// loop until all data has been processed
$start = 0;
$lastbinds = 0;
$this->begin();
while ($start < $datacount) {
$ins = array();
$bindscount = min(self::MAX_BULK_DATA, $datacount - $start);
if ($bindscount != $lastbinds) {
// prepare the binds
$binds = substr(str_repeat(',?', count($datafields)), 1);
$binds = substr(str_repeat(",($binds)", $bindscount), 1);
$lastbinds = $bindscount;
}
for ($go = $start, $last = $start + $bindscount; $go < $last; $go++) {
if (is_object($data[$go])) {
try {
foreach($datafields as $propname) {
$rfl = new ReflectionProperty($data[$go], $propname);
$rfl->setAccessible(true);
$ins[] = $rfl->getValue($data[$go]);
}
}
catch(ReflectionException $e) {
throw new InvalidArgumentException('PDOCONNECT_ERR_SQL_UNKNOWN_PROPERTY', 0, $e);
}
}
else {
foreach($data[$go] as $value) {
$ins[] = $value;
}
}
}
$sql = sprintf('INSERT INTO %s (%s) VALUES %s', $tablename, join(',',$datafields), $binds);
Log::trace($sql);
$stmt = $this->pdo->prepare($sql);
$stmt->execute($ins);
$start = $last;
$result += $bindscount;
}
$this->commit();
}
catch(PDOException $e) {
// do something with the exception if necessary
throw $e;
}
}
catch(Exception $e) {
$this->rollback();
throw $e;
}
return $result;
}
}