如何使用 Laravel 4.2 在单个查询(不是 for 查询循环)中批量插入或更新

Posted

技术标签:

【中文标题】如何使用 Laravel 4.2 在单个查询(不是 for 查询循环)中批量插入或更新【英文标题】:How to mass insert or update in a single query (not a for loop of queries) using Laravel 4.2 【发布时间】:2015-10-16 04:03:38 【问题描述】:
$cardQueryList = [];
foreach($cards as $cardName => $quantity) 
    $cardQueryList[] = [
        'username' => $user->username,
        'card_uid' => $card->uid,
        'have_quantity' => $quantity
    ];


Collection::insert($cardQueryList);

即使行存在,上面的代码也会创建新行。我怎样才能做到这一点,如果该行存在,它会更新。如果它不创建行?一个雄辩或流利的答案是最佳的,但如果没有其他方法,我愿意接受。

我想使用单个查询进行大规模更新/插入。不是每条记录的查询循环。理想情况下,出于显而易见的原因,我想访问数据库一次。

我也已经查看了以下链接:

Insert a new record if not exist and update if exist, laravel eloquent

以上适用于单个记录更新/插入。如果我用 for 循环运行会很慢。我正在寻找一个允许在单个查询中进行大规模插入/更新的答案。

注意:我使用“username”和“card_uid”作为我的密钥。因此,基本上当我找到具有所述用户名和 card_uid 的行时,我想更新相应的行。否则创建一个新行。

【问题讨论】:

你知道如何用 raw-sql 做到这一点吗?不雄辩或查询构建器 @M0rtiis:这是个好问题。我需要一点时间才能弄清楚。 mysql 不是我的强项。 你应该阅读这个dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html @M0riis:感谢您的链接。我去看看。 @M0riis:我尝试通过 Eloquent 和/或 Fluent 的一个原因是因为 Laravel 会检查这些值是否有效,所以进行注入攻击要困难得多。 【参考方案1】:

通常,您将使用的 sql 类型类似于以下内容:-

    insert into `TABLE` ( `FIELD1`,`FIELD2`, `FIELD3` ) values ( 'VALUE1','VALUE2','VALUE3' )
    on duplicate key
        update
            `FIELD1`='VALUE1',
            `FIELD2`='VALUE2',
            `FIELD1`='VALUE3';

我无法告诉你如何在 laravel 中使用它!糟糕 - 忘记更新部分中的字段名称

【讨论】:

我很感激您的回复!问题,当我使用“用户名”和“card_uid”作为我的密钥时,它将如何检查代码的关键部分?那么基本上是否存在带有 card_uid 的用户名? 这篇文章可能很有趣***.com/questions/28078484/…【参考方案2】:
<?php

$valuesArray = [];

foreach( $cards as $cardName => $quantity ) 

    $valuesArray[] = "('".$user->username."','".$card->uid."','".$quantity."')";   


$db->query 
(
    "INSERT INTO `TABLE` ( `username`,`card_uid`, `have_quantity` ) VALUES ".implode( ',', $valuesArray )."
    ON DUPLICATE KEY UPDATE `have_quantity` = VALUES(`have_quantity`);"
 );

确保您在用户名和 card_uid 上有一个主键。也不要忘记转义值并仅在 $valuesArray 不为空时运行查询。

【讨论】:

【参考方案3】:

如果您不希望重复,请让您的数据库架构阻止重复条目的输入。在这种情况下捕获错误并继续。

【讨论】:

感谢您的回复。你能举个例子说明你在代码中的意思吗?【参考方案4】:

你可以试试这个:

Collection::firstOrNew([
    'username' => $user->username,
    'card_uid' => $card->uid,
    'have_quantity' => $cards['quantity']
])
->save();

要使其正常工作,请在您的 Collection 模型中添加具有大量可分配字段名称的 $fillable 属性,例如:

protected $fillable = ['username', 'card_uid', 'have_quantity'];

【讨论】:

我的模型目前有这样的 $fillable 设置:protected $fillable = ['username', 'card_uid', 'have_quantity', 'want_quantity'];我不确定我是否在关注 save() 部分?您能否提供一个填充 2 行或更多行的示例? 可以批量操作吗?好像只有单身

以上是关于如何使用 Laravel 4.2 在单个查询(不是 for 查询循环)中批量插入或更新的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 4.2 雄辩的动态查询

Laravel 5.2 查询生成器作为单个数组(不是 2D 或 3D)

laravel的多态关联--morphTo和morphMany

如何在 Laravel 4.2 中创建自定义 DB Query Builder 方法

Laravel系列4.2查询构造器

在 Laravel 4.2 Artisan 命令中更改应用程序 url