Laravel 5.1在复制时创建或更新

时间:2015-07-25 08:20:22

标签: laravel laravel-5 eloquent query-builder

在Laravel 5.1中,对于MySQL插入,我想查看记录是否已存在并在重复时更新,或者如果不存在则创建新记录。

我已经搜索过那些旧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是该表中的唯一外键,我想更新记录(如果存在)或创建新记录。我试过搜索5.1文档但无法找到我需要的信息。有人可以在这里指导我吗...

6 个答案:

答案 0 :(得分:33)

根据Eloquent模型方法的定义“updateOrCreate()”

  

function updateOrCreate(array $ attributes,array $ values = []){}

需要两个参数......

  1. 如果记录存在,则一个是您要在数据库中检查的属性
  2. 第二个是您要创建或更新的新属性值
  3. AppInfo::updateOrCreate(['app_id' => $postData['appId']],
                            ['contact_email' => $postData['contactEmail']]);
    

答案 1 :(得分:14)

我正在回答这个问题,因为我找不到任何与ON DUPLICATE KEY UPDATE相关的答案,尽管我使用 Laravel 5.4 。 如果您查看Laravel核心代码中的updateOrCreate方法,您将看到所有Laravel使用2个不同的查询后:一个用于更新,另一个用于create。因此,有时您可以在数据库中获取重复数据。所以在某些情况下,编写这种原始查询会很有用:

  

DB :: statement(“INSERT INTO table_namecol_1col_2)VALUES(?,   ?)ON DUPLICATE KEY UPDATE col_1 = col_1 + 1“,([val_1,val_2]));

希望它对某人有用。

答案 2 :(得分:6)

我创建了一个包,用于在重复键上插入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);

答案 3 :(得分:3)

将以下方法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'

如果您已启用或已禁用,该方法会自动添加/删除Eloquent时间戳。

答案 4 :(得分:3)

要使用laravel功能 updateOrCreate ,您需要在表格中自动增加ID

他们正在做的是

select id from your_table where your_attributes

之后获取自动增量ID

然后

update your_table set your_values where field_id

答案 5 :(得分:1)

在我的情况下,这是由模型表中自动递增键的简单不匹配引起的。

获取当前的最大ID:

SELECT max(id) from companies

然后将序列值设置为更高:

select setval('companies_id_seq', 164);

消除了错误。