0

我有一个遍历数组的 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 循环之外运行它吗?

4

1 回答 1

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()(connects to PDO)、$this->begin()(starts transaction)$this->commit()和,以及类似于 Apache Commons 的 Logging$this->rollback()静态类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;
    }
}
于 2013-10-17T14:07:25.863 回答