【问题标题】:How to save multiple records with one query in Laravel?如何在 Laravel 中一次查询保存多条记录?
【发布时间】:2015-12-11 01:25:02
【问题描述】:

我手头有超过 100,000 条记录,为 Array of STD Objects(可以转换为 Array of ArraysArray of Eloquent Models)。

如何使用1个查询将它们全部存储在数据库中。

如果您想知道我从另一个数据库连接中获取这些数据以将它们保存到我的数据库中。

当然,我可以构建每个 Eloquent 模型并调用 save() 函数,但这会花费很多时间,因此不建议这样做。 我在模型上尝试了insert(),将一个 Eloquent 模型数组传递给它,但由于某些原因没有奏效!!

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

我在这里使用 Laravel 4.2。

【问题讨论】:

  • 按照 Taylor Otwell 的说法:“老实说,只需为此使用查询生成器。这样会更有效率,也更有意义。” - github.com/laravel/framework/issues/1295
  • 我觉得在laravel中也定义了savemany的函数,如果你分享一些代码就好了。
  • @DavidStromberg 如果您可以分享一些代码来演示如何使用查询生成器执行此操作,或者使用哪些函数会非常有帮助。
  • @AnshulMishra saveMany 是当您有关系时,您可以将它们全部保存在一起,效果非常好。但这不是我的情况。而且代码非常复杂(不是我的):D

标签: php mysql laravel laravel-4 eloquent


【解决方案1】:

您可以在 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 语句,或者您可以将插入分成足够小的块以适合当前 @ 987654327@ 大小(默认 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);
}

【讨论】:

  • 这正是我试图做的但没有奏效(显然是因为数据的大小)。这可能是一个有效的方法。但是我的数据量很大,这不适用于它(在某些表上超过 200,000 条记录)。
  • @MahmoudZalt 我已经更新了我的答案。我假设您遇到了“数据包太大”的问题。如果这不是您遇到的错误,那是什么“不起作用”?
猜你喜欢
  • 2013-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-29
  • 1970-01-01
  • 2017-08-20
  • 1970-01-01
  • 2020-12-31
相关资源
最近更新 更多