Laravel Bulk UPDATE

13,907

Solution 1

In case someone land in this page like me, laravel allows a bulk update as:

$affectedRows = Voucher::where('id', '=', $voucher->id)->update(array('slug' => Str::random(32)));

See "Updating A Retrieved Model" under http://laravel.com/docs/4.2/eloquent#insert-update-delete

Solution 2

I have created My Custom function for Multiple Update like update_batch in CodeIgniter.

Just place this function in any of your model or you can create helper class and place this function in that class:

//test data
/*
$multipleData = array(
   array(
      'title' => 'My title' ,
      'name' => 'My Name 2' ,
      'date' => 'My date 2'
   ),
   array(
      'title' => 'Another title' ,
      'name' => 'Another Name 2' ,
      'date' => 'Another date 2'
   )
)
*/

/*
 * ----------------------------------
 * update batch 
 * ----------------------------------
 * 
 * multiple update in one query
 *
 * tablename( required | string )
 * multipleData ( required | array of array )
 */
static function updateBatch($tableName = "", $multipleData = array()){

    if( $tableName && !empty($multipleData) ) {

        // column or fields to update
        $updateColumn = array_keys($multipleData[0]);
        $referenceColumn = $updateColumn[0]; //e.g id
        unset($updateColumn[0]);
        $whereIn = "";

        $q = "UPDATE ".$tableName." SET "; 
        foreach ( $updateColumn as $uColumn ) {
            $q .=  $uColumn." = CASE ";

            foreach( $multipleData as $data ) {
                $q .= "WHEN ".$referenceColumn." = ".$data[$referenceColumn]." THEN '".$data[$uColumn]."' ";
            }
            $q .= "ELSE ".$uColumn." END, ";
        }
        foreach( $multipleData as $data ) {
            $whereIn .= "'".$data[$referenceColumn]."', ";
        }
        $q = rtrim($q, ", ")." WHERE ".$referenceColumn." IN (".  rtrim($whereIn, ', ').")";

        // Update  
        return DB::update(DB::raw($q));

    } else {
        return false;
    }
}

It will Produces:

UPDATE `mytable` SET `name` = CASE
WHEN `title` = 'My title' THEN 'My Name 2'
WHEN `title` = 'Another title' THEN 'Another Name 2'
ELSE `name` END,
`date` = CASE 
WHEN `title` = 'My title' THEN 'My date 2'
WHEN `title` = 'Another title' THEN 'Another date 2'
ELSE `date` END
WHERE `title` IN ('My title','Another title')
Share:
13,907
Rob
Author by

Rob

Updated on July 20, 2022

Comments

  • Rob
    Rob almost 2 years

    I'm trying to update a table containing a slug value with random slugs for each record.

    $vouchers = Voucher->get(); // assume 10K for example
    
    foreach ($vouchers as $voucher) {
        $q .= "UPDATE vouchers set slug = '" . Str::random(32) . "' WHERE id = " . $voucher->id . ";";
    }
    
    DB::statement($q);
    

    There are about 2 million records so I need to perform this as a bulk. Doing it as separate records is taking way too long. I can't seem to find a way to bulk run them, say in groups of 10K or something.

    Tried a bunch of variations of ->update() and DB::statement but can't seem to get it to go.