Insert Duplicate Key Update is a quick way to do mass insert.
It's a trait meant to be used with Laravel's Eloquent ORM.
use Illuminate\Database\Eloquent\Model;
use Yadakhov\InsertOnDuplicateKey;
/**
* Class User.
*/
class User extends Model
{
// The function is implemented as a trait.
use InsertOnDuplicateKey;
}
$users = [
['id' => 1, 'email' => 'user1@email.com', 'name' => 'User One'],
['id' => 2, 'email' => 'user2@email.com', 'name' => 'User Two'],
['id' => 3, 'email' => 'user3@email.com', 'name' => 'User Three'],
];
Important: the order of the keys are important. It should be the same for every arrays.
The reason is the code uses array_values()
.
Do not do this:
$users = [
['id' => 1, 'email' => 'user1@email.com', 'name' => 'User One'],
['email' => 'user2@email.com', 'id' => 2, 'name' => 'User Two'],
['email' => 'user3@email.com', 'name' => 'User Three', 'id' => 3],
];
User::insertOnDuplicateKey($users);
-- produces this query
INSERT INTO `users`(`id`,`email`,`name`) VALUES
(1,'user1@email.com','User One'), (2,'user3@email.com','User Two'), (3,'user3email.com','User Three')
ON DUPLICATE KEY UPDATE `id` = VALUES(`id`), `email` = VALUES(`email`), `name` = VALUES(`name`)
User::insertOnDuplicateKey($users, ['email']);
-- produces this query
INSERT INTO `users`(`id`,`email`,`name`) VALUES
(1,'user1@email.com','User One'), (2,'user3@email.com','User Two'), (3,'user3email.com','User Three')
ON DUPLICATE KEY UPDATE `email` = VALUES(`email`)
If users have a numeric column we would like, for example, to sum:
$users = [
['id' => 1, 'name' => 'User One', 'heritage' => 1000],
['id' => 2, 'name' => 'User Two', 'heritage' => 2000],
['id' => 3, 'name' => 'User Three', 'heritage' => 1500],
];
User::insertOnDuplicateKey($users, ['heritage' => DB::raw('`heritage` + VALUES(`heritage`)')]);
-- produces this query
INSERT INTO `users`(`id`,`email`,`name`) VALUES
(1,'user1@email.com','User One'), (2,'user3@email.com','User Two'), (3,'user3email.com','User Three')
ON DUPLICATE KEY UPDATE `heritage` = `heritage` + VALUES(`heritage`)
User::insertIgnore($users);
-- produces this query
INSERT IGNORE INTO `users`(`id`,`email`,`name`) VALUES
(1,'user1@email.com','User One'), (2,'user3@email.com','User Two'), (3,'user3email.com','User Three');
User::replace($users);
-- produces this query
REPLACE INTO `users`(`id`,`email`,`name`) VALUES
(1,'user1@email.com','User One'), (2,'user3@email.com','User Two'), (3,'user3email.com','User Three');
created_at and updated_at will not be updated automatically. To update you can pass the fields in the insert array.
['id' => 1, 'email' => 'user1@email.com', 'name' => 'User One', 'created_at' => Carbon::now(), 'updated_at' => Carbon::now()]
./vendor/bin/phpunit
No. On Duplicate Key Update is only available on MySQL. Postgresql 9.4 has a similar feature called UPSERT. Implementing UPSERT is left as an exercise for the reader.
It is similar but not the same. The updateOrCreate() will only work for one row at a time which doesn't allow bulk insert. InsertOnDuplicateKey will work on many rows.