Laravel 5.1 重复创建或更新
Laravel 5.1 Create or Update on Duplicate
在 Laravel 5.1 中,对于 MySQL 插入,我想查看记录是否已存在并在重复时更新或如果存在 none 则创建新记录。
我已经搜索过旧 laravel 版本的答案。在其中一个旧主题中,它说去年在核心中添加了一个新的 updateOrCreate()
方法。但是当我尝试这样做时,出现错误:
Integrity constraint violation: 1062 Duplicate entry '1' for key 'app_id'
这是我使用的查询:
AppInfo::updateOrCreate(array(
'app_id' => $postData['appId'],
'contact_email' => $postData['contactEmail']
));
其中 app_id
是 table 中的唯一外键,我想更新记录(如果存在)或创建一个新记录。我尝试搜索 5.1 文档,但找不到我需要的信息。有人可以在这里指导我吗...
根据 Eloquent 模型方法的定义 "updateOrCreate()"
function updateOrCreate(array $attributes, array $values = []){}
它需要两个参数...
- 一个是您想要在数据库中检查记录是否存在的属性
- 第二个是您要创建或更新的新属性值
AppInfo::updateOrCreate(['app_id' => $postData['appId']],
['contact_email' => $postData['contactEmail']]);
将以下方法 insertUpdate 添加到您的模型
<?php
namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['name', 'email', 'password'];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = ['password', 'remember_token'];
public static function insertUpdate(array $attributes = [])
{
$model = new static($attributes);
$model->fill($attributes);
if ($model->usesTimestamps()) {
$model->updateTimestamps();
}
$attributes = $model->getAttributes();
$query = $model->newBaseQueryBuilder();
$processor = $query->getProcessor();
$grammar = $query->getGrammar();
$table = $grammar->wrapTable($model->getTable());
$keyName = $model->getKeyName();
$columns = $grammar->columnize(array_keys($attributes));
$insertValues = $grammar->parameterize($attributes);
$updateValues = [];
if ($model->primaryKey !== null) {
$updateValues[] = "{$grammar->wrap($keyName)} = LAST_INSERT_ID({$keyName})";
}
foreach ($attributes as $k => $v) {
$updateValues[] = sprintf("%s = '%s'", $grammar->wrap($k), $v);
}
$updateValues = join(',', $updateValues);
$sql = "insert into {$table} ({$columns}) values ({$insertValues}) on duplicate key update {$updateValues}";
$id = $processor->processInsertGetId($query, $sql, array_values($attributes));
$model->setAttribute($keyName, $id);
return $model;
}
}
您可以使用:
App\User::insertUpdate([
'name' => 'Marco Pedraza',
'email' => 'mpdrza@gmail.com'
]);
它将执行的下一个查询:
insert into `users` (`name`, `email`, `updated_at`, `created_at`) values (?, ?, ?, ?) on duplicate key update `id` = LAST_INSERT_ID(id),`name` = 'Marco Pedraza',`email` = 'mpdrza@gmail.com',`updated_at` = '2016-11-02 01:30:05',`created_at` = '2016-11-02 01:30:05'
如果您启用或禁用,该方法会自动 add/remove Eloquent 时间戳。
要使用 laravel 函数 updateOrCreate,您需要在 table.[=12 中自动 increment id =]
他们正在做的是
select id from your_table where your_attributes
之后获取自增 id
然后
update your_table set your_values where field_id
我创建了一个包来使用 MySQL 插入重复键。
可能对其他人有用:
https://packagist.org/packages/yadakhov/insert-on-duplicate-key
示例:
/**
* Class User.
*/
class User extends Model
{
use Yadakhov\InsertOnDuplicateKey;
...
}
// associative array must match column names
$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'],
];
User::insertOnDuplicateKey($users);
我正在回答这个问题,因为虽然我使用的是 Laravel 5.4,但我找不到与重复密钥更新相关的任何答案。
如果您查看 Laravel 核心代码中的 updateOrCreate 方法,您会发现 Laravel 正在使用 2 个不同的查询:一个用于更新,另一个用于创建。因此,有时您会在数据库中获得重复的数据。所以在某些情况下,编写这种原始查询可能很有用:
DB::statement("INSERT INTO table_name
(col_1
, col_2
) VALUES (?,
?) ON DUPLICATE KEY UPDATE col_1
= col_1
+ 1", ([val_1, val_2]));
希望对大家有用。
在我的例子中,这是由于我的模型 table 中自动递增键的简单不匹配引起的。
获取当前最大id:
SELECT max(id) from companies
然后将序列值设置大一:
select setval('companies_id_seq', 164);
消除了错误。
在 Laravel 5.1 中,对于 MySQL 插入,我想查看记录是否已存在并在重复时更新或如果存在 none 则创建新记录。
我已经搜索过旧 laravel 版本的答案。在其中一个旧主题中,它说去年在核心中添加了一个新的 updateOrCreate()
方法。但是当我尝试这样做时,出现错误:
Integrity constraint violation: 1062 Duplicate entry '1' for key 'app_id'
这是我使用的查询:
AppInfo::updateOrCreate(array(
'app_id' => $postData['appId'],
'contact_email' => $postData['contactEmail']
));
其中 app_id
是 table 中的唯一外键,我想更新记录(如果存在)或创建一个新记录。我尝试搜索 5.1 文档,但找不到我需要的信息。有人可以在这里指导我吗...
根据 Eloquent 模型方法的定义 "updateOrCreate()"
function updateOrCreate(array $attributes, array $values = []){}
它需要两个参数...
- 一个是您想要在数据库中检查记录是否存在的属性
- 第二个是您要创建或更新的新属性值
AppInfo::updateOrCreate(['app_id' => $postData['appId']],
['contact_email' => $postData['contactEmail']]);
将以下方法 insertUpdate 添加到您的模型
<?php
namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['name', 'email', 'password'];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = ['password', 'remember_token'];
public static function insertUpdate(array $attributes = [])
{
$model = new static($attributes);
$model->fill($attributes);
if ($model->usesTimestamps()) {
$model->updateTimestamps();
}
$attributes = $model->getAttributes();
$query = $model->newBaseQueryBuilder();
$processor = $query->getProcessor();
$grammar = $query->getGrammar();
$table = $grammar->wrapTable($model->getTable());
$keyName = $model->getKeyName();
$columns = $grammar->columnize(array_keys($attributes));
$insertValues = $grammar->parameterize($attributes);
$updateValues = [];
if ($model->primaryKey !== null) {
$updateValues[] = "{$grammar->wrap($keyName)} = LAST_INSERT_ID({$keyName})";
}
foreach ($attributes as $k => $v) {
$updateValues[] = sprintf("%s = '%s'", $grammar->wrap($k), $v);
}
$updateValues = join(',', $updateValues);
$sql = "insert into {$table} ({$columns}) values ({$insertValues}) on duplicate key update {$updateValues}";
$id = $processor->processInsertGetId($query, $sql, array_values($attributes));
$model->setAttribute($keyName, $id);
return $model;
}
}
您可以使用:
App\User::insertUpdate([
'name' => 'Marco Pedraza',
'email' => 'mpdrza@gmail.com'
]);
它将执行的下一个查询:
insert into `users` (`name`, `email`, `updated_at`, `created_at`) values (?, ?, ?, ?) on duplicate key update `id` = LAST_INSERT_ID(id),`name` = 'Marco Pedraza',`email` = 'mpdrza@gmail.com',`updated_at` = '2016-11-02 01:30:05',`created_at` = '2016-11-02 01:30:05'
如果您启用或禁用,该方法会自动 add/remove Eloquent 时间戳。
要使用 laravel 函数 updateOrCreate,您需要在 table.[=12 中自动 increment id =]
他们正在做的是
select id from your_table where your_attributes
之后获取自增 id
然后
update your_table set your_values where field_id
我创建了一个包来使用 MySQL 插入重复键。
可能对其他人有用:
https://packagist.org/packages/yadakhov/insert-on-duplicate-key
示例:
/**
* Class User.
*/
class User extends Model
{
use Yadakhov\InsertOnDuplicateKey;
...
}
// associative array must match column names
$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'],
];
User::insertOnDuplicateKey($users);
我正在回答这个问题,因为虽然我使用的是 Laravel 5.4,但我找不到与重复密钥更新相关的任何答案。 如果您查看 Laravel 核心代码中的 updateOrCreate 方法,您会发现 Laravel 正在使用 2 个不同的查询:一个用于更新,另一个用于创建。因此,有时您会在数据库中获得重复的数据。所以在某些情况下,编写这种原始查询可能很有用:
DB::statement("INSERT INTO
table_name
(col_1
,col_2
) VALUES (?, ?) ON DUPLICATE KEY UPDATEcol_1
=col_1
+ 1", ([val_1, val_2]));
希望对大家有用。
在我的例子中,这是由于我的模型 table 中自动递增键的简单不匹配引起的。
获取当前最大id:
SELECT max(id) from companies
然后将序列值设置大一:
select setval('companies_id_seq', 164);
消除了错误。