如何在Laravel中使用一个查询保存多个记录?

时间:2015-09-14 22:40:31

标签: php mysql laravel laravel-4 eloquent

我手中有超过100,000条记录,Array of Arrays(可以转换为Array of Eloquent Modelssave())。

如何使用 1查询将所有这些文件存储在数据库中。

如果您想知道我从其他数据库连接获取这些数据以将其保存到我的数据库中。

当然我可以构建每个Eloquent模型并调用insert()函数,但这需要花费很多时间,无论如何都不推荐。 我尝试了模型上的{{1}}传递给了一个Eloquent模型数组,但由于某些原因没有工作!!

那么除了生成原始SQL查询之外,我还有哪些选项?

我在这里使用Laravel 4.2。

1 个答案:

答案 0 :(得分:4)

您可以在Model上使用insert()方法,但它必须是数组数组。您还需要确保所有数组条目具有相同的键。如果某个条目缺少某个键,则该条目的插入值可能会关闭。

你提到你从一系列对象开始。您可以将此对象数组转换为数组数组,然后使用insert语句。

假设您有Book型号:

$data = [
    (object) [
        'title' => 'Title 1',
        'author' => 'Author 1',
        'publisher' => 'Publisher 1',
    ],
    (object) [
        'title' => 'Title 2',
        'author' => 'Author 2',
        'publisher' => null, // make sure key exists; use null value;
    ],
];

// Convert your objects to arrays. You can use array_walk instead,
// if you prefer to just modify the original $data
$arrayData = array_map(function($value) {
    return (array) $value;
}, $data);

// do the insert
$success = Book::insert($arrayData);

// view last query run (to confirm one bulk insert statement)
$log = DB::getQueryLog();
print_r(end($log));

我不知道有关现有数据的详细信息,因此您可能需要一些更复杂的逻辑来确保数组是正确的,但以上是应该起作用的要点。

修改

在进行这样的批量插入时,还需要注意max_allowed_packet MySQL变量。此变量的默认值为1 MB,因此如果生成大于1 MB的SQL语句,则会出现错误。 max_allowed_packet documentation

所以,如果这是你的问题,你可以升级max_allowed_packet MySQL变量,使其大到足以包含你的整个SQL语句,或者你可以将插入分解成足够小的块以适应当前max_allowed_packet大小(默认为1 MB)。

分块插页的一个例子:

// assume $arrayData is your array of arrays

// you can come up with some fancy algorithm to determine your optimal
// chunk size if you want. 
$size = 100;

$chunks = array_chunk($arrayData, $size);
foreach($chunks as $chunk) {
    Book::insert($chunk);
}